1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Scott Putterman <putterman@netscape.com>
24 : * Pierre Phaneuf <pp@ludusdesign.com>
25 : * Chase Tingley <tingley@sundell.net>
26 : * Neil Deakin <enndeakin@sympatico.ca>
27 : *
28 : * Alternatively, the contents of this file may be used under the terms of
29 : * either of the GNU General Public License Version 2 or later (the "GPL"),
30 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 : * in which case the provisions of the GPL or the LGPL are applicable instead
32 : * of those above. If you wish to allow use of your version of this file only
33 : * under the terms of either the GPL or the LGPL, and not to allow others to
34 : * use your version of this file under the terms of the MPL, indicate your
35 : * decision by deleting the provisions above and replace them with the notice
36 : * and other provisions required by the GPL or the LGPL. If you do not delete
37 : * the provisions above, a recipient may use your version of this file under
38 : * the terms of any one of the MPL, the GPL or the LGPL.
39 : *
40 : * ***** END LICENSE BLOCK *****
41 : *
42 : * This Original Code has been modified by IBM Corporation.
43 : * Modifications made by IBM described herein are
44 : * Copyright (c) International Business Machines
45 : * Corporation, 2000
46 : *
47 : * Modifications to Mozilla code or documentation
48 : * identified per MPL Section 3.3
49 : *
50 : * Date Modified by Description of modification
51 : * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
52 : * use in OS2
53 : */
54 :
55 : /*
56 : This sort service is used to sort template built content or content by attribute.
57 : */
58 :
59 : #include "nsCOMPtr.h"
60 : #include "nsCOMArray.h"
61 : #include "nsTArray.h"
62 : #include "nsIContent.h"
63 : #include "nsIXULTemplateResult.h"
64 : #include "nsIXULTemplateQueryProcessor.h"
65 : #include "nsIXULSortService.h"
66 : #include "nsCycleCollectionParticipant.h"
67 :
68 : enum nsSortState_direction {
69 : nsSortState_descending,
70 : nsSortState_ascending,
71 : nsSortState_natural
72 : };
73 :
74 : // the sort state holds info about the current sort
75 : struct nsSortState
76 0 : {
77 : bool initialized;
78 : bool invertSort;
79 : bool inbetweenSeparatorSort;
80 : bool sortStaticsLast;
81 : bool isContainerRDFSeq;
82 :
83 : PRUint32 sortHints;
84 :
85 : nsSortState_direction direction;
86 : nsAutoString sort;
87 : nsCOMArray<nsIAtom> sortKeys;
88 :
89 : nsCOMPtr<nsIXULTemplateQueryProcessor> processor;
90 : nsCOMPtr<nsIContent> lastContainer;
91 : bool lastWasFirst, lastWasLast;
92 :
93 0 : nsSortState()
94 : : initialized(false),
95 0 : sortHints(0)
96 : {
97 0 : }
98 0 : void Traverse(nsCycleCollectionTraversalCallback &cb) const
99 : {
100 0 : cb.NoteXPCOMChild(processor);
101 0 : cb.NoteXPCOMChild(lastContainer);
102 0 : }
103 : };
104 :
105 : // information about a particular item to be sorted
106 0 : struct contentSortInfo {
107 : nsCOMPtr<nsIContent> content;
108 : nsCOMPtr<nsIContent> parent;
109 : nsCOMPtr<nsIXULTemplateResult> result;
110 0 : void swap(contentSortInfo& other)
111 : {
112 0 : content.swap(other.content);
113 0 : parent.swap(other.parent);
114 0 : result.swap(other.result);
115 0 : }
116 : };
117 :
118 : ////////////////////////////////////////////////////////////////////////
119 : // ServiceImpl
120 : //
121 : // This is the sort service.
122 : //
123 : class XULSortServiceImpl : public nsIXULSortService
124 : {
125 : protected:
126 0 : XULSortServiceImpl(void) {}
127 0 : virtual ~XULSortServiceImpl(void) {}
128 :
129 : friend nsresult NS_NewXULSortService(nsIXULSortService** mgr);
130 :
131 : private:
132 :
133 : public:
134 : // nsISupports
135 : NS_DECL_ISUPPORTS
136 :
137 : // nsISortService
138 : NS_DECL_NSIXULSORTSERVICE
139 :
140 : /**
141 : * Set sort and sortDirection attributes when a sort is done.
142 : */
143 : void
144 : SetSortHints(nsIContent *aNode, nsSortState* aSortState);
145 :
146 : /**
147 : * Set sortActive and sortDirection attributes on a tree column when a sort
148 : * is done. The column to change is the one with a sort attribute that
149 : * matches the sort key. The sort attributes are removed from the other
150 : * columns.
151 : */
152 : void
153 : SetSortColumnHints(nsIContent *content,
154 : const nsAString &sortResource,
155 : const nsAString &sortDirection);
156 :
157 : /**
158 : * Determine the list of items which need to be sorted. This is determined
159 : * in the following way:
160 : * - for elements that have a content builder, get its list of generated
161 : * results
162 : * - otherwise, for trees, get the child treeitems
163 : * - otherwise, get the direct children
164 : */
165 : nsresult
166 : GetItemsToSort(nsIContent *aContainer,
167 : nsSortState* aSortState,
168 : nsTArray<contentSortInfo>& aSortItems);
169 :
170 : /**
171 : * Get the list of items to sort for template built content
172 : */
173 : nsresult
174 : GetTemplateItemsToSort(nsIContent* aContainer,
175 : nsIXULTemplateBuilder* aBuilder,
176 : nsSortState* aSortState,
177 : nsTArray<contentSortInfo>& aSortItems);
178 :
179 : /**
180 : * Sort a container using the supplied sort state details.
181 : */
182 : nsresult
183 : SortContainer(nsIContent *aContainer, nsSortState* aSortState);
184 :
185 : /**
186 : * Given a list of sortable items, reverse the list. This is done
187 : * when simply changing the sort direction for the same key.
188 : */
189 : nsresult
190 : InvertSortInfo(nsTArray<contentSortInfo>& aData,
191 : PRInt32 aStart, PRInt32 aNumItems);
192 :
193 : /**
194 : * Initialize sort information from attributes specified on the container,
195 : * the sort key and sort direction.
196 : *
197 : * @param aRootElement the element that contains sort attributes
198 : * @param aContainer the container to sort, usually equal to aRootElement
199 : * @param aSortKey space separated list of sort keys
200 : * @param aSortDirection direction to sort in
201 : * @param aSortState structure filled in with sort data
202 : */
203 : static nsresult
204 : InitializeSortState(nsIContent* aRootElement,
205 : nsIContent* aContainer,
206 : const nsAString& aSortKey,
207 : const nsAString& aSortDirection,
208 : nsSortState* aSortState);
209 :
210 : /**
211 : * Compares aLeft and aRight and returns < 0, 0, or > 0. The sort
212 : * hints are checked for case matching and integer sorting.
213 : */
214 : static PRInt32 CompareValues(const nsAString& aLeft,
215 : const nsAString& aRight,
216 : PRUint32 aSortHints);
217 : };
|