OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
41 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.ui.group;
15
 
67 ilm 16
import org.openconcerto.utils.Tuple2;
17
 
41 ilm 18
import java.util.ArrayList;
83 ilm 19
import java.util.Collection;
41 ilm 20
import java.util.Collections;
21
import java.util.Comparator;
22
import java.util.List;
23
 
180 ilm 24
/**
25
 * Allow to customize UI layout.
26
 *
27
 * @author guillaume
28
 */
67 ilm 29
public class Group extends Item {
41 ilm 30
 
73 ilm 31
    public static Group copy(final Group g, final Group newParent) {
32
        return new Group(g, newParent);
41 ilm 33
    }
34
 
73 ilm 35
    private static final Comparator<Tuple2<Item, Integer>> COMPARATOR = new Comparator<Tuple2<Item, Integer>>() {
36
        @Override
37
        public int compare(final Tuple2<Item, Integer> o1, final Tuple2<Item, Integer> o2) {
38
            int c = o1.get1().compareTo(o2.get1());
39
            if (c == 0) {
40
                c = o1.get0().getId().compareTo(o2.get0().getId());
41
            }
42
            return c;
43
        }
44
    };
41 ilm 45
 
73 ilm 46
    private int order;
47
    private final List<Tuple2<Item, Integer>> list;
41 ilm 48
 
156 ilm 49
    private String tabId;
50
 
73 ilm 51
    public Group(final String id) {
52
        this(id, LayoutHints.DEFAULT_GROUP_HINTS);
41 ilm 53
    }
54
 
73 ilm 55
    public Group(final String id, final LayoutHints hint) {
56
        super(id, hint);
57
        this.order = 100;
58
        this.list = new ArrayList<Tuple2<Item, Integer>>();
41 ilm 59
    }
60
 
73 ilm 61
    public Group(final Group g, final Group newParent) {
62
        super(g, newParent);
63
        this.order = g.order;
64
        this.list = new ArrayList<Tuple2<Item, Integer>>(g.list.size());
65
        for (final Tuple2<Item, Integer> t : g.list) {
66
            final Item copy = Item.copy(t.get0(), this);
67
            this.list.add(new Tuple2<Item, Integer>(copy, t.get1()));
68
        }
41 ilm 69
    }
70
 
180 ilm 71
    public final Group toImmutable() {
72
        return this.toImmutable(true);
73
    }
74
 
75
    public final Group toImmutable(final boolean onlyDesc) {
76
        if (this.isFrozen())
77
            return this;
78
 
79
        final Group res;
80
        if (onlyDesc) {
81
            res = copy(this, null);
82
            res.freeze();
83
        } else {
84
            final List<String> p = this.getAbsolutePath();
85
            final Group copy = copy(this.getRoot(), null);
86
            copy.freeze();
87
            res = copy.followPath(p, false);
88
        }
89
        assert res.isFrozen();
90
        return res;
91
    }
92
 
67 ilm 93
    @Override
180 ilm 94
    protected synchronized void _freeze() {
95
        super._freeze();
73 ilm 96
        for (final Tuple2<Item, Integer> child : this.list) {
180 ilm 97
            child.get0()._freeze();
41 ilm 98
        }
99
    }
100
 
73 ilm 101
    public Item addItem(final String string) {
102
        final Item res = new Item(string);
103
        this.add(res);
104
        return res;
105
    }
41 ilm 106
 
73 ilm 107
    public Item addItem(final String string, final LayoutHints hint) {
108
        final Item res = new Item(string, hint);
109
        this.add(res);
110
        return res;
41 ilm 111
    }
112
 
73 ilm 113
    public void add(final Item item) {
114
        add(item, this.order);
41 ilm 115
    }
116
 
73 ilm 117
    public void add(final Item item, final int order) {
118
        checkFrozen("add");
119
        item.setParent(this);
120
        this.list.add(new Tuple2<Item, Integer>(item, order));
121
        Collections.sort(this.list, COMPARATOR);
122
        if (this.order <= order) {
123
            this.order = (order / 100) * 100 + 100;
41 ilm 124
        }
125
    }
126
 
73 ilm 127
    public final int getSize() {
41 ilm 128
        return this.list.size();
129
    }
130
 
73 ilm 131
    public final boolean isEmpty() {
41 ilm 132
        return this.list.isEmpty();
133
    }
134
 
73 ilm 135
    public Item getItem(final int index) {
67 ilm 136
        return this.list.get(index).get0();
41 ilm 137
    }
138
 
73 ilm 139
    public Integer getOrder(final int index) {
140
        return this.list.get(index).get1();
41 ilm 141
    }
142
 
73 ilm 143
    public boolean contains(final String id) {
144
        return getDescFromID(id) != null;
41 ilm 145
    }
146
 
94 ilm 147
    public final Collection<Group> getDescendantGroups() {
148
        final List<Group> res = new ArrayList<Group>();
149
        this.getDescendantGroups(res);
150
        return res;
151
    }
152
 
153
    protected void getDescendantGroups(final Collection<Group> res) {
154
        for (final Tuple2<Item, Integer> t : this.list) {
155
            if (t.get0() instanceof Group) {
156
                Group g = (Group) t.get0();
157
                res.add(g);
158
                g.getDescendantGroups(res);
159
            }
160
        }
161
    }
162
 
67 ilm 163
    @Override
83 ilm 164
    public final Collection<Item> getDescendantItems() {
165
        final List<Item> res = new ArrayList<Item>();
166
        this.getDescendantItems(res);
167
        return res;
168
    }
169
 
170
    @Override
171
    protected void getDescendantItems(final Collection<Item> res) {
172
        for (final Tuple2<Item, Integer> t : this.list) {
173
            t.get0().getDescendantItems(res);
174
        }
175
    }
176
 
177
    @Override
73 ilm 178
    public Item getDescFromID(final String id, final int maxLevel) {
179
        final Item res = super.getDescFromID(id, maxLevel);
180
        if (res != null || maxLevel == 0)
181
            return res;
182
        final int size = this.getSize();
183
        final int nextLevel = maxLevel < 0 ? maxLevel : maxLevel - 1;
184
        for (int i = 0; i < size; i++) {
185
            final Item desc = this.getItem(i).getDescFromID(id, nextLevel);
186
            if (desc != null) {
187
                return desc;
188
            }
189
        }
190
        return null;
67 ilm 191
    }
192
 
73 ilm 193
    /**
194
     * Get a descendant group.
195
     *
196
     * @param path a list of IDs.
197
     * @param create <code>true</code> if missing descendant should be created.
198
     * @return the descendant, or <code>null</code> if <code>create</code> is <code>false</code> and
199
     *         the descendant is missing.
200
     */
201
    public final Group followPath(final List<String> path, final boolean create) {
202
        final int size = path.size();
203
        Group g = this;
204
        for (int i = 0; i < size; i++) {
205
            final String id = path.get(i);
206
            final Item child = g.getChildFromID(id);
207
            if (child instanceof Group) {
208
                g = (Group) child;
209
            } else if (child != null) {
210
                throw new IllegalStateException("ID exists but isn't a group : " + child);
211
            } else if (create) {
212
                final Group ng = new Group(id);
213
                g.add(ng);
214
                g = ng;
215
            } else {
216
                return null;
67 ilm 217
            }
218
        }
73 ilm 219
        return g;
67 ilm 220
    }
221
 
73 ilm 222
    public void remove(final String itemId) {
67 ilm 223
        this.remove(this, itemId);
224
    }
225
 
73 ilm 226
    private void remove(final Group group, final String id) {
227
        checkFrozen("remove");
67 ilm 228
        final int size = group.getSize();
229
        for (int i = 0; i < size; i++) {
230
            final Item b = group.getItem(i);
73 ilm 231
            if (b.getId().equals(id)) {
232
                this.list.remove(i);
67 ilm 233
                return;
234
            }
235
            if (b instanceof Group) {
236
                remove((Group) b, id);
237
            }
238
        }
239
 
240
    }
241
 
73 ilm 242
    public Integer getOrder(final String id) {
67 ilm 243
        final int size = this.getSize();
244
        for (int i = 0; i < size; i++) {
73 ilm 245
            final Tuple2<Item, Integer> b = this.list.get(i);
67 ilm 246
            if (b.get0().getId().equals(id)) {
247
                return b.get1();
248
            }
249
        }
250
        return null;
251
    }
252
 
73 ilm 253
    public int getIndex(final String id) {
67 ilm 254
        final int size = this.getSize();
255
        for (int i = 0; i < size; i++) {
73 ilm 256
            final Tuple2<Item, Integer> b = this.list.get(i);
67 ilm 257
            if (b.get0().getId().equals(id)) {
258
                return i;
259
            }
260
        }
261
        return -1;
262
    }
263
 
73 ilm 264
    public String printTree() {
265
        final StringBuilder b = new StringBuilder();
266
        printTree(b, 0, 1);
267
        return b.toString();
268
    }
269
 
270
    @Override
271
    protected void printTree(final StringBuilder builder, final int localOrder, final int level) {
272
        for (int i = 0; i < level - 1; i++) {
273
            builder.append("  ");
274
        }
275
        builder.append("+-+ ");
276
        builder.append(localOrder + " " + this.getId() + " [" + this.getLocalHint() + "]\n");
277
        for (final Tuple2<Item, Integer> tuple : this.list) {
278
            tuple.get0().printTree(builder, tuple.get1(), level + 1);
279
        }
280
    }
281
 
282
    public String printTwoColumns() {
283
        final StringBuilder b = new StringBuilder("==== Group " + this.getId() + " ====\n");
284
        printColumns(b, 2, 0, 0, 1);
285
        return b.toString();
286
    }
287
 
288
    @Override
289
    protected int printColumns(final StringBuilder builder, final int width, int x, final int localOrder, final int level) {
290
        if (this.getLocalHint().isSeparated()) {
291
            x = 0;
292
            builder.append(" -------\n");
293
        }
294
        if (isEmpty()) {
295
            // print a leaf
296
            x = super.printColumns(builder, width, x, localOrder, level);
297
        } else {
298
            // Subgroup
299
            for (final Tuple2<Item, Integer> tuple : this.list) {
300
                final Item subGroup = tuple.get0();
301
                final Integer subGroupOrder = tuple.get1();
302
                x = subGroup.printColumns(builder, width, x, subGroupOrder, level + 1);
303
            }
304
        }
305
        return x;
306
    }
307
 
308
    @Override
309
    public boolean equalsDesc(Object obj) {
310
        if (this == obj)
311
            return true;
312
        if (!super.equalsDesc(obj))
313
            return false;
314
        if (getClass() != obj.getClass())
315
            return false;
316
        final Group other = (Group) obj;
317
        final int size = this.list.size();
318
        if (size != other.list.size())
319
            return false;
320
        for (int i = 0; i < size; i++) {
321
            final Tuple2<Item, Integer> thisChild = this.list.get(i);
322
            final Tuple2<Item, Integer> oChild = other.list.get(i);
323
            if (!thisChild.get1().equals(oChild.get1()) || !thisChild.get0().equalsDesc(oChild.get0()))
324
                return false;
325
        }
326
        return true;
327
    }
156 ilm 328
 
329
    public void setTabId(String tabId) {
330
        this.tabId = tabId;
331
    }
332
 
333
    public String getTabId() {
334
        return this.tabId;
335
    }
41 ilm 336
}