Exemplo n.º 1
0
// https://w3c.github.io/web-animations/#set-the-current-time
void
Animation::SetCurrentTime(const TimeDuration& aSeekTime)
{
  // Return early if the current time has not changed. However, if we
  // are pause-pending, then setting the current time to any value
  // including the current value has the effect of aborting the
  // pause so we should not return early in that case.
  if (mPendingState != PendingState::PausePending &&
      Nullable<TimeDuration>(aSeekTime) == GetCurrentTime()) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  SilentlySetCurrentTime(aSeekTime);

  if (mPendingState == PendingState::PausePending) {
    // Finish the pause operation
    mHoldTime.SetValue(aSeekTime);
    mStartTime.SetNull();

    if (mReady) {
      mReady->MaybeResolve(this);
    }
    CancelPendingTasks();
  }

  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemplo n.º 2
0
// https://w3c.github.io/web-animations/#set-the-animation-playback-rate
void
Animation::SetPlaybackRate(double aPlaybackRate)
{
  if (aPlaybackRate == mPlaybackRate) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  Nullable<TimeDuration> previousTime = GetCurrentTime();
  mPlaybackRate = aPlaybackRate;
  if (!previousTime.IsNull()) {
    SetCurrentTime(previousTime.Value());
  }

  // In the case where GetCurrentTime() returns the same result before and
  // after updating mPlaybackRate, SetCurrentTime will return early since,
  // as far as it can tell, nothing has changed.
  // As a result, we need to perform the following updates here:
  // - update timing (since, if the sign of the playback rate has changed, our
  //   finished state may have changed),
  // - dispatch a change notification for the changed playback rate, and
  // - update the playback rate on animations on layers.
  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemplo n.º 3
0
// https://w3c.github.io/web-animations/#finish-an-animation
void
Animation::Finish(ErrorResult& aRv)
{
  if (mPlaybackRate == 0 ||
      (mPlaybackRate > 0 && EffectEnd() == TimeDuration::Forever())) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  // Seek to the end
  TimeDuration limit =
    mPlaybackRate > 0 ? TimeDuration(EffectEnd()) : TimeDuration(0);
  bool didChange = GetCurrentTime() != Nullable<TimeDuration>(limit);
  SilentlySetCurrentTime(limit);

  // If we are paused or play-pending we need to fill in the start time in
  // order to transition to the finished state.
  //
  // We only do this, however, if we have an active timeline. If we have an
  // inactive timeline we can't transition into the finished state just like
  // we can't transition to the running state (this finished state is really
  // a substate of the running state).
  if (mStartTime.IsNull() &&
      mTimeline &&
      !mTimeline->GetCurrentTime().IsNull()) {
    mStartTime.SetValue(mTimeline->GetCurrentTime().Value() -
                        limit.MultDouble(1.0 / mPlaybackRate));
    didChange = true;
  }

  // If we just resolved the start time for a pause or play-pending
  // animation, we need to clear the task. We don't do this as a branch of
  // the above however since we can have a play-pending animation with a
  // resolved start time if we aborted a pause operation.
  if (!mStartTime.IsNull() &&
      (mPendingState == PendingState::PlayPending ||
       mPendingState == PendingState::PausePending)) {
    if (mPendingState == PendingState::PausePending) {
      mHoldTime.SetNull();
    }
    CancelPendingTasks();
    didChange = true;
    if (mReady) {
      mReady->MaybeResolve(this);
    }
  }
  UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Sync);
  if (didChange && IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemplo n.º 4
0
void
Animation::UpdateTiming(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag)
{
  // Update the sequence number each time we transition in or out of the
  // idle state
  if (!IsUsingCustomCompositeOrder()) {
    if (PlayState() == AnimationPlayState::Idle) {
      mSequenceNum = kUnsequenced;
    } else if (mSequenceNum == kUnsequenced) {
      mSequenceNum = sNextSequenceNum++;
    }
  }

  // We call UpdateFinishedState before UpdateEffect because the former
  // can change the current time, which is used by the latter.
  UpdateFinishedState(aSeekFlag, aSyncNotifyFlag);
  UpdateEffect();

  // Unconditionally Add/Remove from the timeline. This is ok because if the
  // animation has already been added/removed (which will be true more often
  // than not) the work done by AnimationTimeline/DocumentTimeline is still
  // negligible and its easier than trying to detect whenever we are switching
  // to/from being relevant.
  //
  // We need to do this after calling UpdateEffect since it updates some
  // cached state used by IsRelevant.
  //
  // Note that we only store relevant animations on the timeline since they
  // are the only ones that need ticks and are the only ones returned from
  // AnimationTimeline::GetAnimations. Storing any more than that would mean
  // that we fail to garbage collect irrelevant animations since the timeline
  // keeps a strong reference to each animation.
  //
  // Once we tick animations from the their timeline, and once we expect
  // timelines to go in and out of being inactive, we will also need to store
  // non-idle animations that are waiting for their timeline to become active
  // on their timeline (as otherwise once the timeline becomes active it will
  // have no way of notifying its animations). For now, however, we can
  // simply store just the relevant animations.
  if (mTimeline) {
    // FIXME: Once we expect animations to go back and forth betweeen being
    // inactive and active, we will need to store more than just relevant
    // animations on the timeline. This is because an animation might be
    // deemed irrelevant because its timeline is inactive. If it is removed
    // from the timeline at that point the timeline will have no way of
    // getting the animation to add itself again once it becomes active.
    if (IsRelevant()) {
      mTimeline->AddAnimation(*this);
    } else {
      mTimeline->RemoveAnimation(*this);
    }
  }
}
Exemplo n.º 5
0
// https://w3c.github.io/web-animations/#pause-an-animation
void
Animation::DoPause(ErrorResult& aRv)
{
  if (IsPausedOrPausing()) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  // If we are transitioning from idle, fill in the current time
  if (GetCurrentTime().IsNull()) {
    if (mPlaybackRate >= 0.0) {
      mHoldTime.SetValue(TimeDuration(0));
    } else {
      if (EffectEnd() == TimeDuration::Forever()) {
        aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
        return;
      }
      mHoldTime.SetValue(TimeDuration(EffectEnd()));
    }
  }

  bool reuseReadyPromise = false;
  if (mPendingState == PendingState::PlayPending) {
    CancelPendingTasks();
    reuseReadyPromise = true;
  }

  if (!reuseReadyPromise) {
    // Clear ready promise. We'll create a new one lazily.
    mReady = nullptr;
  }

  mPendingState = PendingState::PausePending;

  nsIDocument* doc = GetRenderedDocument();
  if (doc) {
    PendingAnimationTracker* tracker =
      doc->GetOrCreatePendingAnimationTracker();
    tracker->AddPausePending(*this);
  } else {
    TriggerOnNextTick(Nullable<TimeDuration>());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
}
Exemplo n.º 6
0
void CLogChangedPathArray::RemoveIrrelevantPaths()
{
    struct IsRelevant
    {
        bool operator()(const CLogChangedPath& path) const
        {
            return !path.IsRelevantForStartPath();
        }
    };

    iterator first = begin();
    iterator last = end();
    erase (std::remove_copy_if (first, last, first, IsRelevant()), last);

    actions = 0;
}
Exemplo n.º 7
0
// https://w3c.github.io/web-animations/#set-the-animation-start-time
void
Animation::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
{
  if (aNewStartTime == mStartTime) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  Nullable<TimeDuration> timelineTime;
  if (mTimeline) {
    // The spec says to check if the timeline is active (has a resolved time)
    // before using it here, but we don't need to since it's harmless to set
    // the already null time to null.
    timelineTime = mTimeline->GetCurrentTime();
  }
  if (timelineTime.IsNull() && !aNewStartTime.IsNull()) {
    mHoldTime.SetNull();
  }

  Nullable<TimeDuration> previousCurrentTime = GetCurrentTime();
  mStartTime = aNewStartTime;
  if (!aNewStartTime.IsNull()) {
    if (mPlaybackRate != 0.0) {
      mHoldTime.SetNull();
    }
  } else {
    mHoldTime = previousCurrentTime;
  }

  CancelPendingTasks();
  if (mReady) {
    // We may have already resolved mReady, but in that case calling
    // MaybeResolve is a no-op, so that's okay.
    mReady->MaybeResolve(this);
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
  PostUpdate();
}
Exemplo n.º 8
0
// https://w3c.github.io/web-animations/#reverse-an-animation
void
Animation::Reverse(ErrorResult& aRv)
{
  if (!mTimeline || mTimeline->GetCurrentTime().IsNull()) {
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  if (mPlaybackRate == 0.0) {
    return;
  }

  AutoMutationBatchForAnimation mb(*this);

  SilentlySetPlaybackRate(-mPlaybackRate);
  Play(aRv, LimitBehavior::AutoRewind);

  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
}
Exemplo n.º 9
0
// https://w3c.github.io/web-animations/#play-an-animation
void
Animation::DoPlay(ErrorResult& aRv, LimitBehavior aLimitBehavior)
{
  AutoMutationBatchForAnimation mb(*this);

  bool abortedPause = mPendingState == PendingState::PausePending;

  Nullable<TimeDuration> currentTime = GetCurrentTime();
  if (mPlaybackRate > 0.0 &&
      (currentTime.IsNull() ||
       (aLimitBehavior == LimitBehavior::AutoRewind &&
        (currentTime.Value().ToMilliseconds() < 0.0 ||
         currentTime.Value() >= EffectEnd())))) {
    mHoldTime.SetValue(TimeDuration(0));
  } else if (mPlaybackRate < 0.0 &&
             (currentTime.IsNull() ||
              (aLimitBehavior == LimitBehavior::AutoRewind &&
               (currentTime.Value().ToMilliseconds() <= 0.0 ||
                currentTime.Value() > EffectEnd())))) {
    if (EffectEnd() == TimeDuration::Forever()) {
      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
      return;
    }
    mHoldTime.SetValue(TimeDuration(EffectEnd()));
  } else if (mPlaybackRate == 0.0 && currentTime.IsNull()) {
    mHoldTime.SetValue(TimeDuration(0));
  }

  bool reuseReadyPromise = false;
  if (mPendingState != PendingState::NotPending) {
    CancelPendingTasks();
    reuseReadyPromise = true;
  }

  // If the hold time is null then we're either already playing normally (and
  // we can ignore this call) or we aborted a pending pause operation (in which
  // case, for consistency, we need to go through the motions of doing an
  // asynchronous start even though we already have a resolved start time).
  if (mHoldTime.IsNull() && !abortedPause) {
    return;
  }

  // Clear the start time until we resolve a new one. We do this except
  // for the case where we are aborting a pause and don't have a hold time.
  //
  // If we're aborting a pause and *do* have a hold time (e.g. because
  // the animation is finished or we just applied the auto-rewind behavior
  // above) we should respect it by clearing the start time. If we *don't*
  // have a hold time we should keep the current start time so that the
  // the animation continues moving uninterrupted by the aborted pause.
  //
  // (If we're not aborting a pause, mHoldTime must be resolved by now
  //  or else we would have returned above.)
  if (!mHoldTime.IsNull()) {
    mStartTime.SetNull();
  }

  if (!reuseReadyPromise) {
    // Clear ready promise. We'll create a new one lazily.
    mReady = nullptr;
  }

  mPendingState = PendingState::PlayPending;

  nsIDocument* doc = GetRenderedDocument();
  if (doc) {
    PendingAnimationTracker* tracker =
      doc->GetOrCreatePendingAnimationTracker();
    tracker->AddPlayPending(*this);
  } else {
    TriggerOnNextTick(Nullable<TimeDuration>());
  }

  UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
  if (IsRelevant()) {
    nsNodeUtils::AnimationChanged(this);
  }
}
void ColumnManager::ReadSettings
	( DWORD defaultColumns
	, DWORD hideColumns
	, const CString& containerName
	, int maxsize
	, int * widthlist)
{
	// defaults
	DWORD selectedStandardColumns = defaultColumns & ~hideColumns;
	m_dwDefaultColumns = defaultColumns & ~hideColumns;

	columns.resize (maxsize);
	int power = 1;
	for (size_t i = 0; i < maxsize; ++i)
	{
		columns[i].index = static_cast<int>(i);
		if(widthlist==NULL)
			columns[i].width = 0;
		else
			columns[i].width = widthlist[i];
		columns[i].visible = true;
		columns[i].relevant = !(hideColumns & power);
		power *= 2;
	}

//	userProps.clear();

	// where the settings are stored within the registry

	registryPrefix = _T("Software\\TortoiseGit\\StatusColumns\\") + containerName;

	// we accept settings of current version only
	bool valid = (DWORD)CRegDWORD (registryPrefix + _T("Version"), 0xff) == BLAME_COLUMN_VERSION;
	if (valid)
	{
		// read (possibly different) column selection

		selectedStandardColumns = CRegDWORD (registryPrefix, selectedStandardColumns) & ~hideColumns;

		// read user-prop lists

		CString userPropList = CRegString (registryPrefix + _T("UserProps"));
		CString shownUserProps = CRegString (registryPrefix + _T("ShownUserProps"));

		ParseUserPropSettings (userPropList, shownUserProps);

		// read column widths

		CString colWidths = CRegString (registryPrefix + _T("_Width"));

		ParseWidths (colWidths);
	}

	// process old-style visibility setting

	SetStandardColumnVisibility (selectedStandardColumns);

	// clear all previously set header columns

	int c = ((CHeaderCtrl*)(control->GetDlgItem(0)))->GetItemCount()-1;
	while (c>=0)
		control->DeleteColumn(c--);

	// create columns

	for (int i = 0, count = GetColumnCount(); i < count; ++i)
		control->InsertColumn (i, GetName(i), LVCFMT_LEFT, IsVisible(i)&&IsRelevant(i) ? -1 : GetVisibleWidth(i, false));

	// restore column ordering

	if (valid)
		ParseColumnOrder (CRegString (registryPrefix + _T("_Order")));
	else
		ParseColumnOrder (CString());

	ApplyColumnOrder();

	// auto-size the columns so we can see them while fetching status
	// (seems the same values will not take affect in InsertColumn)

	for (int i = 0, count = GetColumnCount(); i < count; ++i)
		if (IsVisible(i))
			control->SetColumnWidth (i, GetVisibleWidth (i, true));
}
Exemplo n.º 11
0
void ColumnManager::OnContextMenuHeader(CWnd* pWnd, CPoint point, bool isGroundEnable /* = false*/)
{
	CHeaderCtrl* pHeaderCtrl = (CHeaderCtrl*)pWnd;
	if ((point.x == -1) && (point.y == -1))
	{
		CRect rect;
		pHeaderCtrl->GetItemRect(0, &rect);
		pHeaderCtrl->ClientToScreen(&rect);
		point = rect.CenterPoint();
	}

	CMenu popup;
	if (popup.CreatePopupMenu())
	{
		int columnCount = GetColumnCount();

		CString temp;
		UINT uCheckedFlags = MF_STRING | MF_ENABLED | MF_CHECKED;
		UINT uUnCheckedFlags = MF_STRING | MF_ENABLED;

		// build control menu

		//temp.LoadString(IDS_STATUSLIST_SHOWGROUPS);
		//popup.AppendMenu(isGroundEnable? uCheckedFlags : uUnCheckedFlags, columnCount, temp);

		temp.LoadString(IDS_STATUSLIST_RESETCOLUMNORDER);
		popup.AppendMenu(uUnCheckedFlags, columnCount + 2, temp);
		popup.AppendMenu(MF_SEPARATOR);

		// standard columns
		AddMenuItem(&popup);

		// user-prop columns:
		// find relevant ones and sort 'em

		std::map<CString, int> sortedProps;
		for (int i = (int)itemName.size(); i < columnCount; ++i)
			if (IsRelevant(i))
				sortedProps[GetName(i)] = i;

		if (!sortedProps.empty())
		{
			// add 'em to the menu

			popup.AppendMenu(MF_SEPARATOR);

			for (auto iter = sortedProps.cbegin(), end = sortedProps.cend(); iter != end; ++iter)
			{
				popup.AppendMenu(IsVisible(iter->second)
					? uCheckedFlags
					: uUnCheckedFlags
					, iter->second
					, iter->first);
			}
		}

		// show menu & let user pick an entry

		int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, pWnd);
		if ((cmd >= 1) && (cmd < columnCount))
			SetVisible(cmd, !IsVisible(cmd));
		else if (cmd == columnCount)
		{
			pWnd->GetParent()->SendMessage(LVM_ENABLEGROUPVIEW, !isGroundEnable, NULL);
			//EnableGroupView(!isGroundEnable);
		}
		else if (cmd == columnCount + 1)
			RemoveUnusedProps();
		else if (cmd == columnCount + 2)
		{
			temp.LoadString(IDS_CONFIRMRESETCOLUMNORDER);
			if (MessageBox(pWnd->m_hWnd, temp, L"TortoiseGit", MB_YESNO | MB_ICONQUESTION) == IDYES)
				ResetColumns(m_dwDefaultColumns);
		}
	}
}