ordlist.cpp

Go to the documentation of this file.
00001 // $Id: ordlist.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // ordlist.cpp -- the OrderedList class
00100 
00101 /*
00102 */
00103 
00104 
00105 #include "camtypes.h"
00106 
00107 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "galstr.h"           // For string resources
00109 #include "ordlist.h"
00110 #include "progress.h"
00111 
00112 
00113 #if TRUE
00114 CC_IMPLEMENT_DYNAMIC(OrderedList, CCObject)
00115 CC_IMPLEMENT_MEMDUMP(ComparatorInfo, ListItem)
00116 CC_IMPLEMENT_MEMDUMP(SequenceItem, ListItem)
00117 CC_IMPLEMENT_MEMDUMP(OrderSequence, ListItem)
00118 
00119 
00120 #define new CAM_DEBUG_NEW
00121 
00122 
00123 /**********************************************************************************************
00124 
00125 >   ComparatorInfo::ComparatorInfo()
00126 
00127     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00128     Created:    20/5/94
00129     Inputs:     -
00130     Outputs:    -
00131     Returns:    -
00132     Purpose:    Constructor for a ComparatorInfo object
00133     Notes:      This constructor should not really be used; if you do use it, then make
00134                 sure that you set at least the SortFn and ResourceID fields of the new
00135                 object to legal values, else OrderedList clients may explode.
00136     SeeAlso:    OrderedList
00137 
00138 **********************************************************************************************/
00139 
00140 ComparatorInfo::ComparatorInfo()
00141 {
00142     SortFn      = NULL;
00143     CanReverse  = TRUE;
00144 }
00145 
00146 
00147 /**********************************************************************************************
00148 
00149 >   ComparatorInfo::ComparatorInfo(const ComparatorInfo &other)
00150 
00151     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00152     Created:    20/5/94
00153     Inputs:     -
00154     Outputs:    -
00155     Returns:    -
00156     Purpose:    Copy constructor for a ComparatorInfo object
00157     Notes:      This constructor should not really be used; if you do use it, then make
00158                 sure that you set at least the SortFn and ResourceID fields of the new
00159                 object to legal values, else OrderedList clients may explode.
00160     SeeAlso:    OrderedList
00161 
00162 **********************************************************************************************/
00163 
00164 ComparatorInfo::ComparatorInfo(const ComparatorInfo &other)
00165 {
00166     SortFn      = other.SortFn;
00167     SortName    = other.SortName;
00168     CanReverse  = other.CanReverse;
00169 }
00170 
00171 
00172 
00173 /**********************************************************************************************
00174 
00175 >   ComparatorInfo::ComparatorInfo(ListComparator Compare, UINT32 SortName, BOOL Reverse = TRUE)
00176 
00177     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00178     Created:    20/5/94
00179     Inputs:     Compare -  The Comparator function used for the sort
00180                 SortName - a resource ID for a string describing the sort
00181                 (e.g. "Sort by Name", "Sort by Date", etc)
00182                 Reverse - TRUE (the default) if the sort can be applied in reverse
00183     Outputs:    -
00184     Returns:    -
00185     Purpose:    Constructor for a ComparatorInfo
00186     SeeAlso:    OrderedList
00187 
00188 **********************************************************************************************/
00189 
00190 ComparatorInfo::ComparatorInfo(ListComparator Compare, UINT32 SortNameID, BOOL Reverse)
00191 {
00192     SortFn      = Compare;
00193     SortName.MakeMsg(SortNameID);
00194     CanReverse  = Reverse;
00195 }
00196 
00197 
00198 
00199 /**********************************************************************************************
00200 
00201 >   ComparatorInfo::ComparatorInfo(ListComparator Compare, const String_32 &Name,
00202                                         BOOL Reverse = TRUE)
00203 
00204     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00205     Created:    20/5/94
00206     Inputs:     Compare -  The Comparator function used for the sort
00207                 Name - a string_32 describing the sort
00208                 (e.g. "Sort by Name", "Sort by Date", etc)
00209                 Reverse - TRUE (the default) if the sort can be applied in reverse
00210     Outputs:    -
00211     Returns:    -
00212     Purpose:    Constructor for a ComparatorInfo
00213                 This allows you to set the name given a String_32, which means that
00214                 'external' entities such as tools can provide sort modes.
00215     SeeAlso:    OrderedList
00216 
00217 **********************************************************************************************/
00218 
00219 ComparatorInfo::ComparatorInfo(ListComparator Compare, const String_32 &Name, BOOL Reverse)
00220 {
00221     SortFn      = Compare;
00222     SortName    = Name;
00223     CanReverse  = Reverse;
00224 }
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 /**********************************************************************************************
00239 
00240 >   SequenceItem::SequenceItem()
00241 
00242     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00243     Created:    18/5/94
00244     Inputs:     -
00245     Outputs:    -
00246     Returns:    -
00247     Purpose:    Constructor for a SequenceItem
00248     SeeAlso:    OrderSequence; OrderedList
00249 
00250 **********************************************************************************************/
00251 
00252 SequenceItem::SequenceItem()
00253 {
00254     MasterItem = NULL;
00255 }
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 /**********************************************************************************************
00271 
00272 >   OrderSequence::OrderSequence()
00273 
00274     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00275     Created:    18/5/94
00276     Inputs:     -
00277     Outputs:    -
00278     Returns:    -
00279     Purpose:    Constructor for a OrderSequence
00280     SeeAlso:    SequenceItem; OrderedList
00281 
00282 **********************************************************************************************/
00283 
00284 OrderSequence::OrderSequence()
00285 {
00286     Comparator  = NULL;
00287     Cached      = FALSE;
00288     Reversed    = FALSE;
00289     UsageCount  = 0;
00290 }
00291 
00292 
00293 
00294 /**********************************************************************************************
00295 
00296 >   OrderSequence::OrderSequence(ListComparator Compare, BOOL Reverse)
00297 
00298     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00299     Created:    18/5/94
00300     Inputs:     Compare - A comparator function which determines the sort order
00301                 Reverse - TRUE if you want the list sorted in reverse order             
00302     Outputs:    -
00303     Returns:    -
00304     Purpose:    Constructor for a OrderSequence
00305     SeeAlso:    SequenceItem; OrderedList; keyword ListComparator
00306 
00307 **********************************************************************************************/
00308 
00309 OrderSequence::OrderSequence(ListComparator Compare, BOOL Reverse)
00310 {
00311     Comparator  = Compare;
00312     Cached      = FALSE;
00313     Reversed    = Reverse;
00314     UsageCount  = 0;
00315 }
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 /**********************************************************************************************
00335 
00336 >   OrderedList::OrderedList() 
00337 
00338     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00339     Created:    16/5/94
00340     Inputs:     -
00341     Outputs:    -
00342     Returns:    -
00343     Purpose:    OrderedList class constructor
00344     Notes:      Remember to call OrderedList::Init() after creating
00345 
00346 **********************************************************************************************/
00347 
00348 OrderedList::OrderedList()
00349 {
00350     SortOrders = NULL;      // This is properly initialised in the Init() function
00351 
00352 
00353     for (INT32 i = 0; i < MaxSortKeys; i++)
00354     {
00355         SortMode[i].Info     = NULL;
00356         SortMode[i].Reversed = FALSE;
00357     }
00358 }
00359 
00360 
00361 
00362 /**********************************************************************************************
00363 
00364 >   OrderedList::~OrderedList() 
00365 
00366     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00367     Created:    16/5/94
00368     Inputs:     -
00369     Outputs:    -
00370     Returns:    -
00371     Purpose:    OrderedList class destructor
00372     Errors:     None
00373 
00374 **********************************************************************************************/
00375 
00376 OrderedList::~OrderedList()
00377 {
00378     // Clear all encapsulated master and sequence items
00379     DeleteAll();
00380 
00381     // Clear away our list of provided sort modes
00382     if (SortOrders != NULL)
00383     {
00384         SortOrders->DeleteAll();
00385         delete SortOrders;
00386     }
00387 
00388     if (!Sequences.IsEmpty())
00389     {
00390 #ifdef _DEBUG
00391 /*
00392         // Warn Jason that someone's being rampant
00393         JCWTRACE( _T("  ** Warning: OrderedList deleted with Sequences non-empty! Cleaning up...\n"));
00394 
00395         ListItem *Ptr = Sequences.GetHead();
00396         while (Ptr != NULL)
00397         {
00398             // Check - if in use, somebody forgot to deselect an order.
00399             if ( ((OrderSequence *) Ptr)->UsageCount > 0 )
00400                 JCWTRACE( _T("    I was forced to delete an in-use sequence!\n"));
00401             Ptr = Sequences.GetNext(Ptr);
00402         }
00403 */
00404 #endif
00405 
00406         Sequences.DeleteAll();
00407     }
00408 }
00409 
00410 
00411 
00412 /**********************************************************************************************
00413 
00414 >   BOOL OrderedList::Init(void)
00415 
00416     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00417     Created:    20/5/94
00418     Inputs:     -
00419     Outputs:    -
00420     Returns:    FALSE if initialisation failed (lack of memory)
00421 
00422     Purpose:    This initialises the OrderedList.
00423 
00424     Notes:      This includes creation of a List of avaliable Sorts.
00425 
00426                 NO LONGER AVAILABLE:
00427                 The OrderedList base class provides only one sort method - "Unsorted"
00428                 Derived classes may override this function if they don't want 'Unsorted'
00429                 to be an available method.
00430                 If you want this, then all you need to do is uncomment this stuff and
00431                 add a string resource baclk in for its name.
00432 
00433 **********************************************************************************************/
00434 
00435 BOOL OrderedList::Init(void)
00436 {
00437     if (SortOrders == NULL)     // Only init if we have not already done so
00438     {
00439         SortOrders = new List;
00440         if (SortOrders == NULL)
00441             return(FALSE);
00442 
00443 //      ComparatorInfo *SortOrder;
00444 //
00445 //      SortOrder = new ComparatorInfo(Unsorted, _R(IDS_SORTBY_UNSORTED), FALSE);
00446 //      if (SortOrder == NULL)
00447 //          return(FALSE);
00448 //
00449 //      SortOrders->AddTail(SortOrder);
00450     }
00451 
00452     return(TRUE);
00453 }
00454 
00455 
00456 
00457 /**********************************************************************************************
00458 
00459 >   BOOL OrderedList::AddItem(ListItem *TheItem)
00460 
00461     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00462     Created:    18/5/94
00463     Inputs:     ListItem - The item to add to the master list
00464     Outputs:    -
00465     Returns:    TRUE if it succeeds, FALSE if there isn't enough memory
00466     Purpose:    Adds the given ListItem to the OrderedList.
00467     Notes       This adds entries to all sequences in this OrderedList which refer
00468                 to the new item in the master list. All lists will be resorted to
00469                 place this item correctly the next time they are SelectOrder'd
00470 
00471 **********************************************************************************************/
00472 
00473 BOOL OrderedList::AddItem(ListItem *TheItem)
00474 {
00475     MasterList.AddTail(TheItem);
00476 
00477     OrderSequence *TheSeq = (OrderSequence *) Sequences.GetHead();
00478     SequenceItem *NewItem;
00479 
00480     while (TheSeq != NULL)
00481     {
00482         TheSeq->Cached = FALSE;                     // This sequence needs re-sorting
00483 
00484         NewItem = new SequenceItem;
00485         if (NewItem == NULL)
00486         {
00487             ENSURE(FALSE, "OrderedList::AddItem failed to allocate new SequenceItem");
00488             return(FALSE);
00489         }
00490 
00491         NewItem->MasterItem = TheItem;              // Set up the new SeqItem
00492         TheSeq->Sequence.AddTail(NewItem);          // Add it to this Sequence
00493 
00494         TheSeq = (OrderSequence *) Sequences.GetNext(TheSeq);   // Move on to the next sequence
00495     }   
00496 
00497     return(TRUE);
00498 }
00499 
00500 
00501 /**********************************************************************************************
00502 
00503 >   ListItem *OrderedList::RemoveMasterItem(ListItem *TheItem)
00504 
00505     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00506     Created:    18/5/94
00507     Inputs:     TheItem - A pointer to the item which you want to remove
00508     Outputs:    -
00509     Returns:    The item that was removed (returns the pointer as passed in)
00510     Purpose:    Delinks the given item from the OrderedList. TheItem is NOT 
00511                 deleted - it is up to you to do this when you're finished with it
00512 
00513     Notes:      (Removes the item from the Master List, and deletes all
00514                 reference to it from all sequence lists. TheItem is NOT deleted)
00515 
00516 **********************************************************************************************/
00517 
00518 ListItem *OrderedList::RemoveMasterItem(ListItem *TheItem)
00519 {
00520     MasterList.RemoveItem(TheItem);
00521 
00522     OrderSequence *TheSeq = (OrderSequence *) Sequences.GetHead();
00523     SequenceItem *SeqItem;
00524 
00525     while (TheSeq != NULL)
00526     {
00527         SeqItem = (SequenceItem *) TheSeq->Sequence.GetHead();
00528         while (SeqItem != NULL)
00529         {
00530             if (TheItem == SeqItem->GetItem())
00531                 break;
00532 
00533             SeqItem = (SequenceItem *) TheSeq->Sequence.GetNext(SeqItem);
00534         }
00535 
00536 
00537         if (SeqItem == NULL)
00538         {
00539             ENSURE(FALSE, "OrderedList::RemoveItem- Expected SequenceItem was not found!");
00540             return(TheItem);
00541         }
00542 
00543         TheSeq->Sequence.RemoveItem(SeqItem);
00544         delete SeqItem;
00545 
00546         TheSeq = (OrderSequence *) Sequences.GetNext(TheSeq); // Move on to the next sequence
00547     }   
00548 
00549     return(TheItem);
00550 }
00551 
00552 
00553 
00554 /**********************************************************************************************
00555 
00556 >   void OrderedList::DeleteAll(void)
00557 
00558     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00559     Created:    18/5/94
00560     Inputs:     -
00561     Outputs:    -
00562     Returns:    -
00563     Purpose:    Removes all items in the OrderedList, calling all their destructors
00564     Notes:      This includes ALL items in all sequences AND THE MASTER LIST held
00565                 by the OrderedList (i.e. deletes all enclosed objects)
00566 
00567 **********************************************************************************************/
00568 
00569 void OrderedList::DeleteAll(void)
00570 {
00571     ListItem *Ptr = MasterList.GetHead();
00572     ListItem *Next;
00573 
00574     while (Ptr != NULL)
00575     {
00576         Next = MasterList.GetNext(Ptr);
00577         RemoveMasterItem(Ptr);
00578         delete Ptr;
00579 
00580         Ptr = Next;
00581     }
00582 }
00583 
00584 
00585 
00586 /**********************************************************************************************
00587 
00588 >   void OrderedList::InvalidateCaches(void)
00589 
00590     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00591     Created:    18/5/94
00592     Inputs:     -
00593     Outputs:    -
00594     Returns:    -
00595     Purpose:    Informs the OrderedList that something you've done to the list or a
00596                 ListItem in it could possibly change the sort order.
00597 
00598     Notes:      This causes all sequences to be resorted (reasonably quick if they're
00599                 already almost in the correct order) the next time they are SelectOrder'd.
00600                 Note that this is done automatically if you add items through the 
00601                 OrderedList interface, so you should only need to call this if you change
00602                 data in a listitem which is (or potentially may be) used as a sort key.
00603                 Note that OrderedList::InvalidateSequenceCache can be used on a single
00604                 Sequence, but this should only be used if you can absolutely positively
00605                 guarantee (beyond a shadow of a doubt and more certainly than a really 
00606                 certain certainty) that your change will only ever affect the sort order
00607                 of that one sequence.
00608 
00609     SeeAlso:    OrderedList::InvalidateSequenceCache
00610 
00611 **********************************************************************************************/
00612 
00613 void OrderedList::InvalidateCaches(void)
00614 {
00615     OrderSequence *TheSeq = (OrderSequence *) Sequences.GetHead();
00616 
00617     while (TheSeq != NULL)
00618     {
00619         TheSeq->Cached = FALSE;
00620         TheSeq = (OrderSequence *) Sequences.GetNext(TheSeq);
00621     }
00622 }
00623 
00624 
00625 
00626 /**********************************************************************************************
00627 
00628 >   OrderSequence *OrderedList::FindSequence(ListComparator Compare, BOOL Reverse)
00629 
00630     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00631     Created:    18/5/94
00632     Inputs:     Compare - A ListComparator function defining the sort order
00633                 Reverse - TRUE if you want a reverse-order sort
00634     Outputs:    -
00635     Returns:    -
00636     Purpose:    Internal list search method. This searches the list of available
00637                 sequences, and returns a pointer to the first one that matches
00638                 the given comparator function, or NULL if there is no such sequence
00639                 available.
00640     Scope:      private
00641 
00642 **********************************************************************************************/
00643 
00644 OrderSequence *OrderedList::FindSequence(ListComparator Compare, BOOL Reverse)
00645 {
00646     if (Compare == NULL)
00647         return(NULL);
00648 
00649     OrderSequence *TheSeq = (OrderSequence *) Sequences.GetHead();
00650 
00651     while (TheSeq != NULL)
00652     {
00653         if (TheSeq->Comparator == Compare && TheSeq->Reversed == Reverse)
00654             return((OrderSequence *) TheSeq);
00655 
00656         TheSeq = (OrderSequence *) Sequences.GetNext(TheSeq); // Move on to the next sequence
00657     }
00658 
00659     return(NULL);
00660 }
00661 
00662 
00663 /**********************************************************************************************
00664 
00665 >   OrderSequence *OrderedList::CreateSequence(ListComparator Compare, BOOL Reverse)
00666 
00667     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00668     Created:    18/5/94
00669     Inputs:     Compare - A ListComparator function defining the sort order
00670                 Reverse - TRUE if you want a reverse-order sort
00671     Outputs:    -
00672     Returns:    -
00673     Purpose:    Internal list maintenance method. If, after calling
00674                 OrderedList::FindSequence, you can't find a given sequence, then
00675                 you can create a new instance of that sequence by calling this function.
00676                 It is added to the end of the list, and no checks for duplicates are made
00677                 (if a duplicate exists, the first one created will always be used)
00678 
00679 **********************************************************************************************/
00680 
00681 OrderSequence *OrderedList::CreateSequence(ListComparator Compare, BOOL Reverse)
00682 {
00683     if (Compare == NULL)
00684         return(NULL);
00685 
00686     OrderSequence *TheSeq;
00687 
00688     TheSeq = new OrderSequence(Compare, Reverse);
00689     if (TheSeq == NULL)
00690         return(NULL);
00691 
00692     Sequences.AddTail(TheSeq);
00693 
00694     ListItem *Ptr = MasterList.GetHead();
00695     SequenceItem *NewItem;
00696 
00697     while (Ptr != NULL)
00698     {
00699         NewItem = new SequenceItem;
00700         if (NewItem == NULL)
00701         {
00702             ENSURE(FALSE, "OrderedList::CreateSequence failed to allocate new SequenceItem");
00703             return(NULL);
00704         }
00705 
00706         NewItem->MasterItem = Ptr;                  // Set up the new SeqItem
00707         TheSeq->Sequence.AddTail(NewItem);          // Add it to this Sequence
00708 
00709         Ptr = MasterList.GetNext(Ptr);
00710     }
00711 
00712     return(TheSeq);
00713 }
00714 
00715 
00716 
00717 /**********************************************************************************************
00718 
00719 >   BOOL OrderedList::SortSequence(OrderSequence *TheSeq)
00720 
00721     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00722     Created:    18/5/94
00723     Inputs:     TheSeq - The OrderSequence to be sorted
00724                 Reverse - TRUE if you want it sorted into reverse order
00725     Outputs:    -
00726     Returns:    -
00727     Purpose:    Internal list maintenance method. Sorts the given sequence into
00728                 order using a sort and the user-supplied comparator function.
00729                 This sounds slow, but (a) we're only intending to sort short lists, so
00730                 should be fast enough, (b) It's not a completely silly implementation, and
00731                 (c) the sort is only used when the sequence is created, and when it gets
00732                 out of order.  In the latter case, it usually means that the list is very
00733                 close to correct sorted order, and only 1 or 2 passes will be needed to
00734                 bring the list back to fully sorted order.
00735                 (Probably if this sort turns out to be slow, it will be best to change
00736                 to a faster sort for the original (creation) sort, and leave this in place
00737                 for resorting the near-correct list)
00738                 Just in case, SlowJob progress indicators are displayed while sorting
00739 
00740 **********************************************************************************************/
00741 
00742 BOOL OrderedList::SortSequence(OrderSequence *TheSeq)
00743 {
00744     if (TheSeq == NULL || TheSeq->Comparator == NULL)   // Error!
00745         return(FALSE);
00746 
00747     if (TheSeq->Cached)         // Well, I reckon it's already sorted. Hah
00748         return(TRUE);
00749 
00750     SequenceItem *ItemA;
00751     SequenceItem *ItemB;
00752     SequenceItem *ItemC;
00753 
00754     BOOL Sorted;
00755     INT32 CompareResult;
00756 
00757 // Commented out 11/1/95 by Markn because Jason told me to. And it fixes one of my bugs.
00758 // Sometimes this gets called when there's already a slow job going (e.g. import with layers with layer gal open).
00759 //
00760 //  BeginSlowJob(-1);           // Show hourglass, with delay, no percentage
00761 
00762     do
00763     {
00764         Sorted = TRUE;          // Assume in sorted order until we have to move an item
00765         ItemA = (SequenceItem *) TheSeq->Sequence.GetHead();
00766     
00767         while (ItemA != NULL)
00768         {
00769             ContinueSlowJob();
00770 
00771             ItemB = (SequenceItem *) TheSeq->Sequence.GetNext(ItemA);
00772             if (ItemB == NULL)      // At end of list, so have finished this pass
00773                 break;
00774  
00775             if (TheSeq->Reversed)
00776                 CompareResult = TheSeq->Comparator(this, ItemB->GetItem(), ItemA->GetItem());
00777             else
00778                 CompareResult = TheSeq->Comparator(this, ItemA->GetItem(), ItemB->GetItem());
00779 
00780             if (CompareResult > 0)
00781             {
00782                 Sorted = FALSE;     // Have to move an item - can't be in order yet
00783 
00784                 // Delink ItemA from the list - it has to move up
00785                 TheSeq->Sequence.RemoveItem(ItemA);
00786 
00787                 // Search for proper position for A...
00788                 ItemC = (SequenceItem *) TheSeq->Sequence.GetNext(ItemB);
00789                 while (ItemC != NULL)
00790                 {
00791                     if (TheSeq->Reversed)
00792                         CompareResult = TheSeq->Comparator(this, ItemC->GetItem(), ItemA->GetItem());
00793                     else
00794                         CompareResult = TheSeq->Comparator(this, ItemA->GetItem(), ItemC->GetItem());
00795 
00796                     if (CompareResult <= 0) // Have found place to drop ItemA...
00797                         break;
00798 
00799                     ItemC = (SequenceItem *) TheSeq->Sequence.GetNext(ItemC);
00800                 }
00801 
00802                 if (ItemC == NULL)
00803                     TheSeq->Sequence.AddTail(ItemA);             // Belongs at end of list
00804                 else
00805                     TheSeq->Sequence.InsertBefore(ItemC, ItemA); // Belongs just before ItemC
00806             }
00807 
00808             ItemA = ItemB;              // Loop, from the next unsorted item
00809         }
00810     } while (!Sorted);
00811 
00812 //  EndSlowJob();       BeginSlowJob() statement see above
00813 
00814     TheSeq->Cached = TRUE;
00815     return(TRUE);
00816 }
00817 
00818 
00819 
00820 /**********************************************************************************************
00821 
00822 >   List *OrderedList::SelectOrder(ListComparator Compare, BOOL Reversed = FALSE)
00823 
00824     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00825     Created:    18/5/94
00826     Inputs:     Compare - a list comparator function which determines how the list
00827                 will be sorted.
00828                 Reversed - TRUE if you wish the list to be sorted using the comparator into
00829                 reverse order.
00830     Outputs:    -
00831     Returns:    A pointer to a List of SequenceItems, sorted as desired, or
00832                 NULL if it failed.
00833 
00834     Purpose:    Selects a given order for use.
00835 
00836                 Once selected, you can traverse the OrderedList much like an ordinary
00837                 list (see the SeeAlso comments) only you'll find that the items are 
00838                 returned by GetNext/Prev in an order dicatated by the ListComparator
00839                 function that you supplied on selection.
00840 
00841     Notes:      Selecting has the following effects:
00842                 * Increments a UsageCount (which is decremented by DeselectOrder)
00843                 - While selected, a sequence cannot be DestroyOrder'd
00844                 * Creates (if necessary) a new sequence within the OrderedList
00845                 * Sorts (if necessary) the list using the given comparator function
00846 
00847                 Sorting occurs when the sequence is first created, and thereafter when
00848                 SelectOrder() is called AND it is determined that the list order may be
00849                 incorrect (when item(s) have been added, or InvalidataeCache menthods
00850                 have been invoked)
00851 
00852                 If an 'Unsorted' order is requested, this actually returns the Master
00853                 List; this can be traversed in exactly the same manner as an OrderedList
00854                 (as normal ListItems also have a GetItem() method).
00855 
00856                 Passing 'Compare' == NULL will ignore the 'Reversed' parameter and 
00857                 simply return the master list.
00858 
00859     SeeAlso:    OrderedList::InvalidateCaches; OrderedList::DeselectOrder;
00860                 OrderedList::DestroyOrder; Keyword ListComparator
00861 
00862 **********************************************************************************************/
00863 
00864 List *OrderedList::SelectOrder(ListComparator Compare, BOOL Reverse)
00865 {
00866     if (Compare == NULL || Compare == Unsorted)
00867         return(&MasterList);
00868 
00869     OrderSequence *TheSeq = FindSequence(Compare, Reverse); // Find existing Seq?
00870 
00871     if (TheSeq == NULL)                                     // No - create new one
00872         TheSeq = CreateSequence(Compare, Reverse);
00873 
00874     if (TheSeq == NULL)                                     // Failed - argh!
00875         return(NULL);
00876 
00877     if (!TheSeq->Cached)                                    // Needs sorting?
00878         SortSequence(TheSeq);
00879 
00880     TheSeq->UsageCount++;                                   // Increment the usage count
00881 
00882     return(&TheSeq->Sequence);
00883 }
00884 
00885 
00886 /**********************************************************************************************
00887 
00888 >   void OrderedList::ReSortOrder(ListComparator Compare, BOOL Reversed = FALSE)
00889 
00890     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00891     Created:    18/5/94
00892     Inputs:     Compare - a list comparator function which determines how the list
00893                 will be sorted.
00894                 Reversed - TRUE if you wish the list to be sorted using the comparator into
00895                 reverse order.
00896     Outputs:    -
00897     Returns:    -
00898     Purpose:    Immediately (re-)sorts the given order. If no such order exists, no
00899                 action is taken (a new order sequence will NOT be created, as this will
00900                 happen anyway if you subsequently try to Select it)
00901                 Normally, if you add an item to the order sequence, it is not sorted into its
00902                 correct position until the next time the order is selected; The item will be
00903                 added at the tail of the list. This allows you to continue scanning the list
00904                 knowing that it has not shifted about under you. However, if adding items to
00905                 the list you may want to immediately force a resort to ensure it is in order
00906                 (if you are not going to SelectOrder on the list before using it again)
00907 
00908                 Passing 'Compare' == NULL will ignore the 'Reversed' parameter and 
00909                 simply do nothing (as this asks you to resort the master list).
00910 
00911 
00912     SeeAlso:    OrderedList::InvalidateCaches; OrderedList::SelectOrder;
00913                 Keyword ListComparator
00914 
00915 **********************************************************************************************/
00916 
00917 void OrderedList::ReSortOrder(ListComparator Compare, BOOL Reverse)
00918 {
00919     OrderSequence *TheSeq = FindSequence(Compare, Reverse); // Find existing Seq?
00920 
00921     if (TheSeq == NULL)                                     // No such seq - exit
00922         return;
00923 
00924     SortSequence(TheSeq);                                   // Force a sort
00925 }
00926 
00927 
00928 
00929 /**********************************************************************************************
00930 
00931 >   void OrderedList::DeselectOrder(ListComparator Compare, BOOL Reversed = FALSE)
00932 
00933     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00934     Created:    18/5/94
00935     Inputs:     Compare - The list comparator function which defined the sort order
00936                 Reversed -  TRUE if you wish to deselect the Reverse-sorted order
00937     Outputs:    -
00938     Returns:    -
00939     Purpose:    This indicates to the OrderedList that you have finished using the given
00940                 sequence (list sort-order). This unlocks the List so that the sequence may
00941                 be deleted using the DestroyOrder function.
00942     Notes:      Passing 'Compare' == NULL will ignore the 'Reversed' parameter and 
00943                 simply 'deselect' the master list (this in fact returns, doing nothing).
00944 
00945     SeeAlso:    OrderedList; OrderedList::SelectOrder; OrderedList::DestroyOrder
00946     Errors:     This ENSUREs that the sequence exists (has been Selected and not yet Destroy'd)
00947                 and that the UsageCount is legal (that Deselect has not been called more often
00948                 than Select)
00949 
00950 **********************************************************************************************/
00951 
00952 void OrderedList::DeselectOrder(ListComparator Compare, BOOL Reversed)
00953 {
00954     if (Compare == NULL || Compare == Unsorted)
00955         return;
00956 
00957     OrderSequence *TheSeq = FindSequence(Compare, Reversed);    // Find existing Seq?   
00958 
00959     ENSURE(TheSeq != NULL, "OrderedList::DeselectOrder called for nonexistent sequence!");
00960     ENSURE(TheSeq->UsageCount > 0, "OrderedList::DeselectOrder called more often than SelectOrder!");
00961 
00962     TheSeq->UsageCount--;                           // Decrement the usage count
00963 }
00964 
00965 
00966 
00967 /**********************************************************************************************
00968 
00969 >   void OrderedList::DestroyOrder(ListComparator Compare, BOOL Reversed = FALSE)
00970 
00971     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00972     Created:    18/5/94
00973     Inputs:     Comparator - The comparator function which determines the sort order
00974                 Reversed - TRUE if you wish to destroy the reverse-sorted order.
00975     Outputs:    -
00976     Returns:    -
00977     Purpose:    Destroys an order sequence. This is not strictly necessary, but allows
00978                 you to make the OrderedList release all memory used by the sequence if
00979                 you know that you no longer need to acces that sort order. (If you may
00980                 want to look at the list again, it is probably more efficient to never
00981                 call Destroy, so that the cached sort order is available to you in the
00982                 future, without having to re-sort the items)
00983 
00984     Notes:      The sequence will ONLY be destroyed if its usage count is zero (if the
00985                 order has been deselected exactly the same number of times it has been
00986                 selected. This means you can call Destroy after every use of the order
00987                 if you wish, and it will be deleted only if nobody else is sharing it.
00988 
00989                 Passing 'Compare' == NULL will ignore the 'Reversed' parameter and 
00990                 simply do nothing (You can't destroy the master list).
00991 
00992     SeeAlso:    OrderedList::SelectOrder; OrderedList::DeselectOrder
00993     Errors:     In the debug build, this ENSURES that you don't try to destroy an order
00994                 which does not exist, and that the order is not in use (selected) when you
00995                 try to destroy it. In the release build, this will just delete the sequence
00996                 if it can be found
00997 
00998 **********************************************************************************************/
00999 
01000 void OrderedList::DestroyOrder(ListComparator Compare, BOOL Reversed)
01001 {
01002     if (Compare == NULL || Compare == Unsorted)
01003         return;
01004 
01005     OrderSequence *TheSeq = FindSequence(Compare, Reversed);    // Find existing Seq?
01006 
01007     ENSURE(TheSeq != NULL, "OrderedList::DestroyOrder called for nonexistent sequence!");
01008 
01009     if (TheSeq != NULL && TheSeq->UsageCount == 0)
01010     {
01011         Sequences.RemoveItem(TheSeq);
01012         TheSeq->Sequence.DeleteAll();
01013         delete TheSeq;
01014     }
01015 }
01016 
01017 
01018 
01019 
01020 /**********************************************************************************************
01021 
01022 >   INT32 OrderedList::Unsorted(OrderedList *ParentList, ListItem *Item1, ListItem *Item2)
01023 
01024     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01025     Created:    18/5/94
01026     Inputs:     ParentList - the OrderedList in which these items are linked
01027                 Item1, Item2 - the two items to be compared
01028     Outputs:    -
01029     Returns:    A negative value if Item1 is considered "less than" Item2
01030 
01031                 A positive value if Item1 is considered "greater than" Item2
01032     
01033                 Zero if Item1 is considered "equal to" Item2
01034 
01035     Purpose:    "Unsorted" List sort ComparatorFunction, and an example of writing
01036                 ListComparators.
01037 
01038                 Determines if two items in an OrderedList need to be swapped during
01039                 a sort operation. The function returns a value indicating if the
01040                 items were considered equal, or if one item was "greater than" or
01041                 "less than" the other.
01042 
01043     Notes:      This particular function always returns zero, so that it imposes no order
01044                 at all upon the list, thus giving an "Unsorted" List order.
01045                 
01046                 Normally, we would code the function to return the 3 possible results
01047                 e.g. If we wish to compare two integers to sort them into ascending
01048                 order, we should return(Item1->IntegerValue - Item2->IntegerValue)
01049                 NOTE, however, that care must be taken to always return an 'INT32' 
01050                 compatible value (i.e. if comparing INT32s, you should code to 
01051                 return -1, 0, or +1, using explicit < and == comparisons)
01052 
01053                 In your own ListComparator functions, you should attempt to check the
01054                 runtime type of the provided ListItems to ensure they are of an
01055                 appropriate type to be sorted using your function.
01056 
01057     SeeAlso:    ListComparator
01058 
01059 **********************************************************************************************/
01060 
01061 INT32 OrderedList::Unsorted(OrderedList *ParentList, ListItem *Item1, ListItem *Item2)
01062 {
01063     return(0);
01064 }
01065 
01066 
01067 
01068 /**********************************************************************************************
01069 
01070 >   List *OrderedList::GetSortOrders(void)
01071 
01072     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01073     Created:    23/5/94
01074     Inputs:     -
01075     Outputs:    -
01076     Returns:    A pointer to a list of ComparatorInfo objects enumerating the
01077                 sort orders available from this OrderedList object.
01078     Purpose:    Find a list of available sorting orders.
01079     SeeAlso:    ComparatorInfo; ListComparator
01080 
01081 **********************************************************************************************/
01082 
01083 List *OrderedList::GetSortOrders(void)
01084 {
01085     return(SortOrders);
01086 }
01087 
01088 
01089 
01090 /**********************************************************************************************
01091 
01092 >   void OrderedList::AddSortOrder(const ComparatorInfo &CompInfo)
01093 
01094     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01095     Created:    25/5/94
01096     Inputs:     CompInfo - a ComparatorInfo object describing the new sort method.
01097                 Note that this will be duplicated and added into the list if such
01098                 a sort is not already in the list.
01099     Outputs:    -
01100     Returns:    -
01101     Purpose:    Add a sort order to the list of those available from this
01102                 OrderedList object.
01103     SeeAlso:    ComparatorInfo; ListComparator
01104 
01105 **********************************************************************************************/
01106 
01107 void OrderedList::AddSortOrder(const ComparatorInfo &CompInfo)
01108 {
01109     ComparatorInfo *Ptr;
01110 
01111     ENSURE(SortOrders != NULL,
01112             "Someone forgot to call OrderedList::Init before calling AddSortOrder");
01113 
01114     if (SortOrders == NULL)
01115         return;
01116 
01117     Ptr = (ComparatorInfo *) SortOrders->GetHead();
01118     while (Ptr != NULL)
01119     {
01120         if (Ptr->GetSortFn() == CompInfo.GetSortFn() &&
01121             Ptr->GetSortName() == CompInfo.GetSortName())
01122             return;         // Already have this sort mode in the list
01123 
01124         Ptr = (ComparatorInfo *) SortOrders->GetNext(Ptr);
01125     }
01126 
01127     // Have failed to find this order in the list, so add it
01128     Ptr = new ComparatorInfo(CompInfo);
01129     if (Ptr != NULL)
01130         SortOrders->AddTail(Ptr);
01131 }
01132 
01133 
01134 #endif

Generated on Sat Nov 10 03:46:22 2007 for Camelot by  doxygen 1.4.4