diff options
Diffstat (limited to 'layout/xul/tree/nsTreeImageListener.cpp')
-rw-r--r-- | layout/xul/tree/nsTreeImageListener.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/layout/xul/tree/nsTreeImageListener.cpp b/layout/xul/tree/nsTreeImageListener.cpp new file mode 100644 index 000000000..f559be042 --- /dev/null +++ b/layout/xul/tree/nsTreeImageListener.cpp @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsTreeImageListener.h" +#include "nsITreeBoxObject.h" +#include "imgIRequest.h" +#include "imgIContainer.h" +#include "nsIContent.h" + +NS_IMPL_ISUPPORTS(nsTreeImageListener, imgINotificationObserver) + +nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame) + : mTreeFrame(aTreeFrame), + mInvalidationSuppressed(true), + mInvalidationArea(nullptr) +{ +} + +nsTreeImageListener::~nsTreeImageListener() +{ + delete mInvalidationArea; +} + +NS_IMETHODIMP +nsTreeImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) +{ + if (aType == imgINotificationObserver::IS_ANIMATED) { + return mTreeFrame ? mTreeFrame->OnImageIsAnimated(aRequest) : NS_OK; + } + + if (aType == imgINotificationObserver::SIZE_AVAILABLE) { + // Ensure the animation (if any) is started. Note: There is no + // corresponding call to Decrement for this. This Increment will be + // 'cleaned up' by the Request when it is destroyed, but only then. + aRequest->IncrementAnimationConsumers(); + } + + if (aType == imgINotificationObserver::FRAME_UPDATE) { + Invalidate(); + } + + return NS_OK; +} + +void +nsTreeImageListener::AddCell(int32_t aIndex, nsITreeColumn* aCol) +{ + if (!mInvalidationArea) { + mInvalidationArea = new InvalidationArea(aCol); + mInvalidationArea->AddRow(aIndex); + } + else { + InvalidationArea* currArea; + for (currArea = mInvalidationArea; currArea; currArea = currArea->GetNext()) { + if (currArea->GetCol() == aCol) { + currArea->AddRow(aIndex); + break; + } + } + if (!currArea) { + currArea = new InvalidationArea(aCol); + currArea->SetNext(mInvalidationArea); + mInvalidationArea = currArea; + mInvalidationArea->AddRow(aIndex); + } + } +} + + +void +nsTreeImageListener::Invalidate() +{ + if (!mInvalidationSuppressed) { + for (InvalidationArea* currArea = mInvalidationArea; currArea; + currArea = currArea->GetNext()) { + // Loop from min to max, invalidating each cell that was listening for this image. + for (int32_t i = currArea->GetMin(); i <= currArea->GetMax(); ++i) { + if (mTreeFrame) { + nsITreeBoxObject* tree = mTreeFrame->GetTreeBoxObject(); + if (tree) { + tree->InvalidateCell(i, currArea->GetCol()); + } + } + } + } + } +} + +nsTreeImageListener::InvalidationArea::InvalidationArea(nsITreeColumn* aCol) + : mCol(aCol), + mMin(-1), // min should start out "undefined" + mMax(0), + mNext(nullptr) +{ +} + +void +nsTreeImageListener::InvalidationArea::AddRow(int32_t aIndex) +{ + if (mMin == -1) + mMin = mMax = aIndex; + else if (aIndex < mMin) + mMin = aIndex; + else if (aIndex > mMax) + mMax = aIndex; +} + +NS_IMETHODIMP +nsTreeImageListener::ClearFrame() +{ + mTreeFrame = nullptr; + return NS_OK; +} |