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 0000000000..a560ada948 --- /dev/null +++ b/layout/xul/tree/nsTreeImageListener.cpp @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "XULTreeElement.h" +#include "imgIRequest.h" +#include "imgIContainer.h" +#include "nsIContent.h" +#include "nsTreeColumns.h" + +using mozilla::dom::XULTreeElement; + +NS_IMPL_ISUPPORTS(nsTreeImageListener, imgINotificationObserver) + +nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame) + : mTreeFrame(aTreeFrame), + mInvalidationSuppressed(true), + mInvalidationArea(nullptr) {} + +nsTreeImageListener::~nsTreeImageListener() { delete mInvalidationArea; } + +void nsTreeImageListener::Notify(imgIRequest* aRequest, int32_t aType, + const nsIntRect* aData) { + if (aType == imgINotificationObserver::IS_ANIMATED) { + if (mTreeFrame) { + mTreeFrame->OnImageIsAnimated(aRequest); + } + return; + } + + 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 (mTreeFrame) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + if (image) { + nsPresContext* presContext = mTreeFrame->PresContext(); + image->SetAnimationMode(presContext->ImageAnimationMode()); + } + } + } + + if (aType == imgINotificationObserver::FRAME_UPDATE) { + Invalidate(); + } +} + +void nsTreeImageListener::AddCell(int32_t aIndex, nsTreeColumn* 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) { + RefPtr<XULTreeElement> tree = + XULTreeElement::FromNodeOrNull(mTreeFrame->GetBaseElement()); + if (tree) { + tree->InvalidateCell(i, currArea->GetCol()); + } + } + } + } + } +} + +nsTreeImageListener::InvalidationArea::InvalidationArea(nsTreeColumn* 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; +} |