| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_comphelper.hxx" |
| #include <com/sun/star/uno/XInterface.hpp> |
| #include <com/sun/star/container/XIndexAccess.hpp> |
| #include <com/sun/star/container/XChild.hpp> |
| #include <comphelper/container.hxx> |
| #include <osl/diagnose.h> |
| |
| //......................................................................... |
| namespace comphelper |
| { |
| //......................................................................... |
| |
| //============================================================================== |
| IndexAccessIterator::IndexAccessIterator(::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xStartingPoint) |
| :m_xStartingPoint(xStartingPoint) |
| ,m_xCurrentObject(NULL) |
| { |
| OSL_ENSURE(m_xStartingPoint.is(), "IndexAccessIterator::IndexAccessIterator : no starting point !"); |
| } |
| |
| IndexAccessIterator::~IndexAccessIterator() {} |
| |
| //------------------------------------------------------------------------------ |
| ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> IndexAccessIterator::Next() |
| { |
| sal_Bool bCheckingStartingPoint = !m_xCurrentObject.is(); |
| // ist die aktuelle Node der Anfangspunkt ? |
| sal_Bool bAlreadyCheckedCurrent = m_xCurrentObject.is(); |
| // habe ich die aktuelle Node schon mal mittels ShouldHandleElement testen ? |
| if (!m_xCurrentObject.is()) |
| m_xCurrentObject = m_xStartingPoint; |
| |
| ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xSearchLoop( m_xCurrentObject); |
| sal_Bool bHasMoreToSearch = sal_True; |
| sal_Bool bFoundSomething = sal_False; |
| while (!bFoundSomething && bHasMoreToSearch) |
| { |
| // pre-order-traversierung |
| if (!bAlreadyCheckedCurrent && ShouldHandleElement(xSearchLoop)) |
| { |
| m_xCurrentObject = xSearchLoop; |
| bFoundSomething = sal_True; |
| } |
| else |
| { |
| // zuerst absteigen, wenn moeglich |
| ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess> xContainerAccess(xSearchLoop, ::com::sun::star::uno::UNO_QUERY); |
| if (xContainerAccess.is() && xContainerAccess->getCount() && ShouldStepInto(xContainerAccess)) |
| { // zum ersten Child |
| ::com::sun::star::uno::Any aElement(xContainerAccess->getByIndex(0)); |
| xSearchLoop = *(::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>*)aElement.getValue(); |
| bCheckingStartingPoint = sal_False; |
| |
| m_arrChildIndizies.push_back((sal_Int32)0); |
| } |
| else |
| { |
| // dann nach oben und nach rechts, wenn moeglich |
| while (m_arrChildIndizies.size() > 0) |
| { // (mein Stack ist nich leer, also kann ich noch nach oben gehen) |
| ::com::sun::star::uno::Reference< ::com::sun::star::container::XChild> xChild(xSearchLoop, ::com::sun::star::uno::UNO_QUERY); |
| OSL_ENSURE(xChild.is(), "IndexAccessIterator::Next : a content has no approriate interface !"); |
| |
| ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xParent( xChild->getParent()); |
| xContainerAccess = ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess>(xParent, ::com::sun::star::uno::UNO_QUERY); |
| OSL_ENSURE(xContainerAccess.is(), "IndexAccessIterator::Next : a content has an invalid parent !"); |
| |
| // den Index, den SearchLoop in diesem Parent hatte, von meinem 'Stack' |
| sal_Int32 nOldSearchChildIndex = m_arrChildIndizies[m_arrChildIndizies.size() - 1]; |
| m_arrChildIndizies.pop_back(); |
| |
| if (nOldSearchChildIndex < xContainerAccess->getCount() - 1) |
| { // auf dieser Ebene geht es noch nach rechts |
| ++nOldSearchChildIndex; |
| // also das naechste Child |
| ::com::sun::star::uno::Any aElement(xContainerAccess->getByIndex(nOldSearchChildIndex)); |
| xSearchLoop = *(::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>*) aElement.getValue(); |
| bCheckingStartingPoint = sal_False; |
| // und dessen Position auf den 'Stack' |
| m_arrChildIndizies.push_back((sal_Int32)nOldSearchChildIndex); |
| |
| break; |
| } |
| // hierher komme ich, wenn es auf der aktuellen Ebene nicht nach rechts geht, dann mache ich eine darueber weiter |
| xSearchLoop = xParent; |
| bCheckingStartingPoint = sal_False; |
| } |
| |
| if ((m_arrChildIndizies.size() == 0) && !bCheckingStartingPoint) |
| { // das ist genau dann der Fall, wenn ich keinen rechten Nachbarn fuer irgendeinen der direkten Vorfahren des |
| // urspruenglichen xSearchLoop gefunden habe |
| bHasMoreToSearch = sal_False; |
| } |
| } |
| |
| if (bHasMoreToSearch) |
| { // ich habe in xSearchLoop jetzt ein Interface eines 'Knotens' meines 'Baumes', den ich noch abtesten kann |
| if (ShouldHandleElement(xSearchLoop)) |
| { |
| m_xCurrentObject = xSearchLoop; |
| bFoundSomething = sal_True; |
| } |
| else |
| if (bCheckingStartingPoint) |
| // ich bin noch am Anfang, konnte nicht absteigen, und habe an diesem Anfang nix gefunden -> nix mehr zu tun |
| bHasMoreToSearch = sal_False; |
| bAlreadyCheckedCurrent = sal_True; |
| } |
| } |
| } |
| |
| if (!bFoundSomething) |
| { |
| OSL_ENSURE(m_arrChildIndizies.size() == 0, "IndexAccessIterator::Next : items left on stack ! how this ?"); |
| Invalidate(); |
| } |
| |
| return m_xCurrentObject; |
| } |
| |
| //......................................................................... |
| } // namespace comphelper |
| //......................................................................... |
| |
| |