File indexing completed on 2024-04-28 11:38:36
0001 /* 0002 * This file is part of the HTML rendering engine for KDE. 0003 * 0004 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #include "rendering/counter_tree.h" 0024 0025 namespace khtml 0026 { 0027 0028 CounterNode::CounterNode(RenderObject *o) 0029 : m_hasCounters(false), m_isVisual(false), 0030 m_value(0), m_count(0), m_parent(nullptr), m_previous(nullptr), m_next(nullptr), 0031 m_renderer(o) {} 0032 0033 CounterNode::~CounterNode() 0034 { 0035 if (m_parent) { 0036 m_parent->removeChild(this); 0037 } 0038 } 0039 0040 void CounterNode::insertAfter(CounterNode *, CounterNode *) 0041 { 0042 Q_ASSERT(false); 0043 } 0044 0045 void CounterNode::removeChild(CounterNode *) 0046 { 0047 Q_ASSERT(false); 0048 } 0049 0050 void CounterNode::remove() 0051 { 0052 if (m_parent) { 0053 m_parent->removeChild(this); 0054 } else { 0055 Q_ASSERT(isReset()); 0056 // abandon our children 0057 CounterNode *n = firstChild(); 0058 for (; n; n = n->m_next) { 0059 n->m_parent = nullptr; 0060 } 0061 } 0062 } 0063 0064 void CounterNode::setHasCounters() 0065 { 0066 m_hasCounters = true; 0067 if (parent()) { 0068 parent()->setHasCounters(); 0069 } 0070 } 0071 0072 void CounterNode::recount(bool first) 0073 { 0074 int old_count = m_count; 0075 if (m_previous) { 0076 m_count = m_previous->count() + m_value; 0077 } else { 0078 assert(m_parent->firstChild() == this); 0079 m_count = m_parent->value() + m_value; 0080 } 0081 if (old_count != m_count && !first) { 0082 setSelfDirty(); 0083 } 0084 if (old_count != m_count || first) { 0085 if (m_parent) { 0086 m_parent->updateTotal(m_count); 0087 } 0088 if (m_next) { 0089 m_next->recount(); 0090 } 0091 } 0092 } 0093 0094 void CounterNode::setSelfDirty() 0095 { 0096 if (m_renderer && m_isVisual) { 0097 m_renderer->setNeedsLayoutAndMinMaxRecalc(); 0098 } 0099 } 0100 0101 void CounterNode::setParentDirty() 0102 { 0103 if (m_renderer && m_isVisual && m_hasCounters) { 0104 m_renderer->setNeedsLayoutAndMinMaxRecalc(); 0105 } 0106 } 0107 0108 CounterReset::CounterReset(RenderObject *o) : CounterNode(o), m_total(0), m_first(nullptr), m_last(nullptr) {} 0109 CounterReset::~CounterReset() {} 0110 0111 void CounterReset::insertAfter(CounterNode *newChild, CounterNode *refChild) 0112 { 0113 Q_ASSERT(newChild); 0114 Q_ASSERT(!refChild || refChild->parent() == this); 0115 0116 newChild->m_parent = this; 0117 newChild->m_previous = refChild; 0118 0119 if (refChild) { 0120 newChild->m_next = refChild->m_next; 0121 refChild->m_next = newChild; 0122 } else { 0123 newChild->m_next = m_first; 0124 m_first = newChild; 0125 } 0126 0127 if (newChild->m_next) { 0128 assert(newChild->m_next->m_previous == refChild); 0129 newChild->m_next->m_previous = newChild; 0130 } else { 0131 assert(m_last == refChild); 0132 m_last = newChild; 0133 } 0134 0135 newChild->recount(true); 0136 } 0137 0138 void CounterReset::removeChild(CounterNode *oldChild) 0139 { 0140 Q_ASSERT(oldChild); 0141 0142 CounterNode *next = oldChild->m_next; 0143 CounterNode *prev = oldChild->m_previous; 0144 0145 if (oldChild->firstChild()) { 0146 CounterNode *first = oldChild->firstChild(); 0147 CounterNode *last = oldChild->lastChild(); 0148 if (prev) { 0149 prev->m_next = first; 0150 first->m_previous = prev; 0151 } else { 0152 assert(m_first == oldChild); 0153 m_first = first; 0154 } 0155 0156 if (next) { 0157 next->m_previous = last; 0158 last->m_next = next; 0159 } else { 0160 assert(m_last == oldChild); 0161 m_last = last; 0162 } 0163 0164 next = first; 0165 while (next) { 0166 next->m_parent = this; 0167 if (next == last) { 0168 break; 0169 } 0170 next = next->m_next; 0171 } 0172 0173 first->recount(true); 0174 } else { 0175 if (prev) { 0176 prev->m_next = next; 0177 } else { 0178 assert(m_first == oldChild); 0179 m_first = next; 0180 } 0181 if (next) { 0182 next->m_previous = prev; 0183 } else { 0184 assert(m_last == oldChild); 0185 m_last = prev; 0186 } 0187 if (next) { 0188 next->recount(); 0189 } 0190 } 0191 0192 oldChild->m_next = nullptr; 0193 oldChild->m_previous = nullptr; 0194 oldChild->m_parent = nullptr; 0195 } 0196 0197 void CounterReset::recount(bool first) 0198 { 0199 int old_count = m_count; 0200 if (m_previous) { 0201 m_count = m_previous->count(); 0202 } else if (m_parent) { 0203 m_count = m_parent->value(); 0204 } else { 0205 m_count = 0; 0206 } 0207 0208 updateTotal(m_value); 0209 if (!first) { 0210 setSelfDirty(); 0211 } 0212 if (first || m_count != old_count) { 0213 if (m_next) { 0214 m_next->recount(); 0215 } 0216 } 0217 } 0218 0219 void CounterReset::setSelfDirty() 0220 { 0221 setParentDirty(); 0222 } 0223 0224 void CounterReset::setParentDirty() 0225 { 0226 if (hasCounters()) { 0227 if (m_renderer && m_isVisual) { 0228 m_renderer->setNeedsLayoutAndMinMaxRecalc(); 0229 } 0230 CounterNode *n = firstChild(); 0231 for (; n; n = n->nextSibling()) { 0232 n->setParentDirty(); 0233 } 0234 } 0235 } 0236 0237 void CounterReset::updateTotal(int value) 0238 { 0239 if (value > m_total) { 0240 m_total = value; 0241 } 0242 } 0243 0244 } // namespace