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