OpenWalnut  1.4.0
WItemSelector.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WITEMSELECTOR_H
00026 #define WITEMSELECTOR_H
00027 
00028 #include <istream>
00029 #include <ostream>
00030 #include <vector>
00031 #include <string>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 #include <boost/signals2/signal.hpp>
00035 
00036 #include "WItemSelection.h"
00037 #include "WItemSelectionItem.h"
00038 
00039 
00040 /**
00041  * This class represents a subset of a WItemSelection. It is a class for managing selections. The class is kept very restrictive. The selection
00042  * can't be edited after the instantiation of the class to keep the interface clean, easily usable and consistent among multiple threads. So
00043  * please DO NOT extend it to provide methods for changing it!
00044  *
00045  * This class can be seen as some kind of special "iterator" providing access to the underlying set without allowing it to be modified. The class
00046  * provides methods to access the whole set and the subset represented by itself. The restrictive interface ensures thread-safety and enforces
00047  * that each new selection is done by a new instance of this class, which is needed by the WPropertyVariable to work properly.
00048  *
00049  * \note the protected constructor avoids instance creation of classes not the WItemSelection. This is restrictive but needed. Nobody can create
00050  * instances of it, changing the underlying WItemSelection and using it as selector for another ItemSelection instance.
00051  */
00052 class WItemSelector // NOLINT
00053 {
00054 friend class WItemSelection;
00055 public:
00056     /**
00057      * The type used for storing index lists. It is a list of integer correlating with the elements in the managed WItemSelection class.
00058      */
00059     typedef  std::vector< size_t > IndexList;
00060 
00061     /**
00062      * Copy constructor. Creates a new copy of the selector and ensure proper signal subscriptions to the underlying selection.
00063      *
00064      * \param other the selector to copy
00065      */
00066     WItemSelector( const WItemSelector& other );
00067 
00068     /**
00069      * Copy assignment. Creates a new copy of the selector and ensure proper signal subscriptions to the underlying selection.
00070      *
00071      * \param other the selector to copy
00072      *
00073      * \return this.
00074      */
00075     WItemSelector& operator=( const WItemSelector & other );
00076 
00077     /**
00078      * Destructor.
00079      */
00080     virtual ~WItemSelector();
00081 
00082     /**
00083      * Creates a new valid instance with the specified items selected. This is especially useful to simply create a new selection if only the old
00084      * selection is known.
00085      *
00086      * \note Please be aware that, in the moment this method returns, another thread can make all selectors invalid again causing the returned
00087      * one to be invalid too. To avoid this, use the newSelector method only if the old has locked the selection using \ref lock and \ref unlock.
00088      *
00089      * \param selected the selected items (their index in WItemSelection).
00090      *
00091      * \return the new selector instance
00092      */
00093     WItemSelector newSelector( IndexList selected ) const;
00094 
00095     /**
00096      * Creates a new valid instance with the specified items selected. This can be useful to add a certain index. The new selector has the
00097      * selection from this AND the specified one. If you want to create a selector containing only one selected item, use the method that uses
00098      * the IndexList.
00099      *
00100      * \note Please be aware that, in the moment this method returns, another thread can make all selectors invalid again causing the returned
00101      * one to be invalid too. To avoid this, use the newSelector method only if the old has locked the selection using \ref lock and \ref unlock.
00102      *
00103      * \param selected the selected item (the index in WItemSelection).
00104      *
00105      * \return the new selector instance
00106      */
00107     WItemSelector newSelector( size_t selected ) const;
00108 
00109     /**
00110      * Creates a new valid instance with the specified items selected. This is especially useful to simply create a new selection if only the
00111      * string representing it is known. This somehow correlates to the << operator.
00112      *
00113      * \note Please be aware that, in the moment this method returns, another thread can make all selectors invalid again causing the returned
00114      * one to be invalid too. To avoid this, use the newSelector method only if the old has locked the selection using \ref lock and \ref unlock.
00115      *
00116      * \param asString the selected items
00117      *
00118      * \return the new selector instance
00119      */
00120     WItemSelector newSelector( const std::string asString ) const;
00121 
00122     /**
00123      * Creates a new selector, but basing on this instance as old one. The new selector tries to keep the old selection but makes the internal
00124      * selection list valid with the current underlying selection.
00125      *
00126      * \note Please be aware that, in the moment this method returns, another thread can make all selectors invalid again causing the returned
00127      * one to be invalid too. To avoid this, use the newSelector method only if the old has locked the selection using \ref lock and \ref unlock.
00128      *
00129      * \return the new (valid) selector.
00130      */
00131     WItemSelector newSelector() const;
00132 
00133     /**
00134      * Compares two selector. They are assumed to be equal if the selected items are equal and if the underlying WItemSelection is the same.
00135      *
00136      * \param other the selector
00137      *
00138      * \return true if equal
00139      */
00140     bool operator==( const WItemSelector& other ) const;
00141 
00142     /**
00143      * Write a selection in string representation to the given output stream.
00144      *
00145      * \param out the output stream where to put the information
00146      *
00147      * \return the output stream extended by the information of this selector
00148      */
00149     std::ostream& operator<<( std::ostream& out ) const;
00150 
00151     /**
00152      * Gives the count of elements in the set of selectable items. This is \ref size + number of unselected items.
00153      *
00154      * \return the number of all items in the item set.
00155      */
00156     virtual size_t sizeAll() const;
00157 
00158     /**
00159      * The number of selected items.
00160      *
00161      * \return the number of selected items.
00162      */
00163     virtual size_t size() const;
00164 
00165     /**
00166      * True if the selection is empty.
00167      *
00168      * \return true if nothing is selected.
00169      */
00170     virtual bool empty() const;
00171 
00172     /**
00173      * Gets the item with the given index from the WItemSelection. This index does not equal the index of the same item for \ref at. This method
00174      * is useful to go through the list of ALL items (not only the selected).
00175      *
00176      * \param index the index
00177      *
00178      * \return the item
00179      */
00180     virtual const boost::shared_ptr< WItemSelectionItem > atAll( size_t index ) const;
00181 
00182     /**
00183      * Gets the selected item with the given index. This is not the same index as the element has in the corresponding WItemSelection!
00184      * This method is especially useful to iterate the through the selected items.
00185      *
00186      * \param index the index
00187      *
00188      * \return the item
00189      */
00190     virtual const boost::shared_ptr< WItemSelectionItem > at( size_t index ) const;
00191 
00192     /**
00193      * Helps to get the index of an selected item in the WItemSelection. This is somehow similar to \ref at, but does not return the item but the
00194      * index to it.
00195      *
00196      * \param index the index in the selection (not the item index in WItemSelection)
00197      *
00198      * \return the index in WItemSelection.
00199      */
00200     virtual size_t getItemIndexOfSelected( size_t index ) const;
00201 
00202     /**
00203      * Checks whether the selection is valid anymore. If a selector is not valid anymore, you should ask the one providing the selectors (most
00204      * probably a WPropSelection) for a new one.
00205      *
00206      * \return true if valid.
00207      */
00208     virtual bool isValid() const;
00209 
00210     /**
00211      * Read locks the underlying selection. This ensure, that the selection stays fixed as long as this selector is locked. This also ensures
00212      * that no invalidation can be issued as long as this selector has the lock. BUT it is possible that an invalidation occurs while this
00213      * selector waits. So please always check for validity of the selector ater locking.
00214      */
00215     void lock();
00216 
00217     /**
00218      * Unlocks the selection again. Always call this after a lock.
00219      */
00220     void unlock();
00221 
00222     /**
00223      * Allow cast from selector to unsigned int.
00224      *
00225      * \return the index of the first selected item in the selection.
00226      */
00227     operator unsigned int() const;
00228 
00229     /**
00230      * Casts the selector to a list of indices currently selected. It contains the list of index in the corresponding WItemSelection. This is
00231      * especially useful if the whole index list is needed without nasty iterations.
00232      *
00233      * \return the list of index.
00234      */
00235     IndexList getIndexList() const;
00236 
00237 protected:
00238     /**
00239      * Constructor creates an selector for the specified selection of items. Noting is selected after construction.
00240      *
00241      * \param selection the selection handled by this instance
00242      * \param selected the set of selected items
00243      */
00244     WItemSelector( boost::shared_ptr< WItemSelection > selection, IndexList selected );
00245 
00246     /**
00247      * The selection handled by this selector.
00248      */
00249     boost::shared_ptr< WItemSelection > m_selection;
00250 
00251     /**
00252      * The list of items currently selected.
00253      */
00254     IndexList m_selected;
00255 
00256     /**
00257      * Stores the connection made using WItemSelection::subscribeInvalidateSignal.
00258      */
00259     boost::signals2::connection m_invalidateSignalConnection;
00260 
00261 private:
00262     /**
00263      * Creates a new selector instance using the specified index list. Handles all needed signal subscription stuff.
00264      *
00265      * \param selected the index list of selected items
00266      *
00267      * \return new selector
00268      */
00269     WItemSelector createSelector( const IndexList& selected ) const;
00270 
00271     /**
00272      * Handles the case of invalidation.
00273      */
00274     void invalidate();
00275 
00276     /**
00277      * If true the selector is valid.
00278      */
00279     bool m_valid;
00280 
00281     /**
00282      * This locks prevents the selection to be modified during selector iteration.
00283      */
00284     WItemSelection::ReadTicket m_lock;
00285 };
00286 
00287 /**
00288  * Write a selection in string representation to the given output stream.
00289  *
00290  * \param out the output stream where to put the information
00291  * \param other the instance to write out
00292  *
00293  * \return the output stream extended by the information of this selector
00294  */
00295 std::ostream& operator<<( std::ostream& out, const WItemSelector& other );
00296 
00297 #endif  // WITEMSELECTOR_H
00298