You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.3 KiB
223 lines
5.3 KiB
/*
|
|
* This file is part of the HTML rendering engine for KDE.
|
|
*
|
|
* Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "rendering/counter_tree.h"
|
|
#include "rendering/render_object.h"
|
|
|
|
namespace khtml {
|
|
|
|
CounterNode::CounterNode(RenderObject *o)
|
|
: m_hasCounters(false), m_isVisual(false),
|
|
m_value(0), m_count(0), m_parent(0), m_previous(0), m_next(0),
|
|
m_renderer(o) {}
|
|
|
|
CounterNode::~CounterNode()
|
|
{
|
|
if (m_parent) m_parent->removeChild(this);
|
|
}
|
|
|
|
void CounterNode::insertAfter ( CounterNode *, CounterNode *)
|
|
{
|
|
Q_ASSERT( false);
|
|
}
|
|
|
|
void CounterNode::removeChild ( CounterNode *)
|
|
{
|
|
Q_ASSERT( false);
|
|
}
|
|
|
|
void CounterNode::remove ()
|
|
{
|
|
if (m_parent) m_parent->removeChild(this);
|
|
else {
|
|
Q_ASSERT(isReset());
|
|
Q_ASSERT(!firstChild());
|
|
Q_ASSERT(!lastChild());
|
|
}
|
|
}
|
|
|
|
void CounterNode::setHasCounters ()
|
|
{
|
|
m_hasCounters = true;
|
|
if (parent())
|
|
parent()->setHasCounters();
|
|
}
|
|
|
|
void CounterNode::recount (bool first)
|
|
{
|
|
int old_count = m_count;
|
|
if (m_previous)
|
|
m_count = m_previous->count() + m_value;
|
|
else {
|
|
assert(m_parent->firstChild() == this);
|
|
m_count = m_parent->value() + m_value;
|
|
}
|
|
if (old_count != m_count && !first)
|
|
setSelfDirty();
|
|
if (old_count != m_count || first) {
|
|
if (m_parent) m_parent->updateTotal(m_count);
|
|
if (m_next) m_next->recount();
|
|
}
|
|
}
|
|
|
|
void CounterNode::setSelfDirty ()
|
|
{
|
|
if (m_renderer && m_isVisual)
|
|
m_renderer->setNeedsLayoutAndMinMaxRecalc();
|
|
}
|
|
|
|
void CounterNode::setParentDirty ()
|
|
{
|
|
if (m_renderer && m_isVisual && m_hasCounters)
|
|
m_renderer->setNeedsLayoutAndMinMaxRecalc();
|
|
}
|
|
|
|
CounterReset::CounterReset(RenderObject *o) : CounterNode(o), m_total(0), m_first(0), m_last(0) {}
|
|
CounterReset::~CounterReset() {}
|
|
|
|
void CounterReset::insertAfter ( CounterNode *newChild, CounterNode *refChild )
|
|
{
|
|
Q_ASSERT( newChild );
|
|
Q_ASSERT( !refChild || refChild->parent() == this );
|
|
|
|
newChild->m_parent = this;
|
|
newChild->m_previous = refChild;
|
|
|
|
if (refChild) {
|
|
newChild->m_next = refChild->m_next;
|
|
refChild->m_next = newChild;
|
|
} else {
|
|
newChild->m_next = m_first;
|
|
m_first = newChild;
|
|
}
|
|
|
|
if (newChild->m_next) {
|
|
assert(newChild->m_next->m_previous == refChild);
|
|
newChild->m_next->m_previous = newChild;
|
|
}
|
|
else {
|
|
assert (m_last == refChild);
|
|
m_last = newChild;
|
|
}
|
|
|
|
newChild->recount(true);
|
|
}
|
|
|
|
void CounterReset::removeChild ( CounterNode *oldChild )
|
|
{
|
|
Q_ASSERT( oldChild );
|
|
|
|
CounterNode* next = oldChild->m_next;
|
|
CounterNode* prev = oldChild->m_previous;
|
|
|
|
if (oldChild->firstChild()) {
|
|
CounterNode* first = oldChild->firstChild();
|
|
CounterNode* last = oldChild->lastChild();
|
|
if (prev) {
|
|
prev->m_next = first;
|
|
first->m_previous = prev;
|
|
}
|
|
else {
|
|
assert ( m_first == oldChild );
|
|
m_first = first;
|
|
}
|
|
|
|
if (next) {
|
|
next->m_previous = last;
|
|
last->m_next = next;
|
|
}
|
|
else {
|
|
assert ( m_last == oldChild );
|
|
m_last = last;
|
|
}
|
|
|
|
next = first;
|
|
while (next) {
|
|
next->m_parent = this;
|
|
if (next == last) break;
|
|
next = next->m_next;
|
|
}
|
|
|
|
first->recount(true);
|
|
}
|
|
else {
|
|
if (prev) prev->m_next = next;
|
|
else {
|
|
assert ( m_first == oldChild );
|
|
m_first = next;
|
|
}
|
|
if (next) next->m_previous = prev;
|
|
else {
|
|
assert ( m_last == oldChild );
|
|
m_last = prev;
|
|
}
|
|
if (next)
|
|
next->recount();
|
|
}
|
|
|
|
|
|
oldChild->m_next = 0;
|
|
oldChild->m_previous = 0;
|
|
oldChild->m_parent = 0;
|
|
}
|
|
|
|
void CounterReset::recount (bool first)
|
|
{
|
|
int old_count = m_count;
|
|
if (m_previous)
|
|
m_count = m_previous->count();
|
|
else if (m_parent)
|
|
m_count = m_parent->value();
|
|
else
|
|
m_count = 0;
|
|
|
|
updateTotal(m_value);
|
|
if (!first) setSelfDirty();
|
|
if (first || m_count != old_count) {
|
|
if (m_next) m_next->recount();
|
|
}
|
|
}
|
|
|
|
void CounterReset::setSelfDirty ()
|
|
{
|
|
setParentDirty();
|
|
}
|
|
|
|
void CounterReset::setParentDirty ()
|
|
{
|
|
if (hasCounters()) {
|
|
if (m_renderer && m_isVisual) m_renderer->setNeedsLayoutAndMinMaxRecalc();
|
|
CounterNode* n = firstChild();
|
|
for(; n; n = n->nextSibling())
|
|
{
|
|
n->setParentDirty();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CounterReset::updateTotal (int value)
|
|
{
|
|
if (value > m_total) m_total = value;
|
|
}
|
|
|
|
} // namespace
|