OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 17 | Rev 41 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 17 Rev 25
Line 14... Line 14...
14
 /*
14
 /*
15
 * Row created on 10 décembre 2005
15
 * Row created on 10 décembre 2005
16
 */
16
 */
17
package org.openconcerto.openoffice.spreadsheet;
17
package org.openconcerto.openoffice.spreadsheet;
18
 
18
 
19
import org.openconcerto.openoffice.XMLVersion;
-
 
20
import org.openconcerto.openoffice.ODDocument;
19
import org.openconcerto.openoffice.ODDocument;
-
 
20
import org.openconcerto.openoffice.StyleDesc;
-
 
21
import org.openconcerto.openoffice.StyleProperties;
-
 
22
import org.openconcerto.openoffice.StyleStyleDesc;
-
 
23
import org.openconcerto.openoffice.XMLVersion;
21
 
24
 
22
import java.util.ArrayList;
25
import java.util.Arrays;
23
import java.util.List;
26
import java.util.List;
24
 
27
 
25
import org.jdom.Element;
28
import org.jdom.Element;
26
 
29
 
27
/**
30
/**
Line 37... Line 40...
37
        return new Element("table-row", ns.getTABLE());
40
        return new Element("table-row", ns.getTABLE());
38
    }
41
    }
39
 
42
 
40
    private final Table<D> parent;
43
    private final Table<D> parent;
41
    private final int index;
44
    private final int index;
-
 
45
    private int repeated;
42
    // the same immutable cell instance is repeated, but each MutableCell is only once
46
    // the same immutable cell instance is repeated, but each MutableCell is only once
43
    // ATTN MutableCell have their index as attribute
47
    // ATTN MutableCell have their index as attribute
-
 
48
    // array is faster than List
44
    private final List<Cell<D>> cells;
49
    private Cell<D>[] cells;
-
 
50
    private int cellCount;
45
 
51
 
46
    Row(Table<D> parent, Element tableRowElem, int index) {
52
    Row(Table<D> parent, Element tableRowElem, int index, StyleDesc<RowStyle> styleDesc, StyleDesc<CellStyle> cellStyleDesc) {
47
        super(parent.getODDocument(), tableRowElem, RowStyle.class);
53
        super(parent.getODDocument(), tableRowElem, styleDesc);
48
        this.parent = parent;
54
        this.parent = parent;
49
        this.index = index;
55
        this.index = index;
-
 
56
        this.repeated = Axis.ROW.getRepeated(getElement());
-
 
57
        @SuppressWarnings("unchecked")
-
 
58
        final Cell<D>[] unsafe = new Cell[parent.getColumnCount()];
50
        this.cells = new ArrayList<Cell<D>>();
59
        this.cells = unsafe;
-
 
60
        this.cellCount = 0;
51
        for (final Element cellElem : this.getCellElements()) {
61
        for (final Element cellElem : this.getCellElements()) {
52
            addCellElem(cellElem);
62
            addCellElem(cellElem, cellStyleDesc);
-
 
63
        }
-
 
64
    }
-
 
65
 
-
 
66
    private final void ensureRoom(int additionalItems) {
-
 
67
        final int requiredSize = this.getCellCount() + additionalItems;
-
 
68
        if (requiredSize > this.cells.length) {
-
 
69
            this.cells = Arrays.copyOf(this.cells, requiredSize);
53
        }
70
        }
54
    }
71
    }
55
 
72
 
56
    protected final Table<D> getSheet() {
73
    protected final Table<D> getSheet() {
57
        return this.parent;
74
        return this.parent;
58
    }
75
    }
59
 
76
 
-
 
77
    // ATTN index of the first row
60
    final int getY() {
78
    final int getY() {
61
        return this.index;
79
        return this.index;
62
    }
80
    }
63
 
81
 
64
    // plain Cell instances have multiple indexes (if repeated) but MutableCell are unique
82
    // inclusive
65
    final int getX(MutableCell<D> c) {
83
    final int getLastY() {
66
        return this.cells.indexOf(c);
84
        return this.getY() + this.getRepeated() - 1;
67
    }
85
    }
68
 
86
 
69
    private void addCellElem(final Element cellElem) {
-
 
70
        final Cell<D> cell = new Cell<D>(this, cellElem);
-
 
71
        this.cells.add(cell);
-
 
72
 
-
 
73
        final String repeatedS = cellElem.getAttributeValue("number-columns-repeated", this.getSheet().getTABLE());
-
 
74
        if (repeatedS != null) {
87
    final int getRepeated() {
75
            final int toRepeat = Integer.parseInt(repeatedS) - 1;
-
 
76
            for (int i = 0; i < toRepeat; i++) {
-
 
77
                this.cells.add(cell);
88
        return this.repeated;
78
            }
89
    }
-
 
90
 
-
 
91
    final void setRepeated(int newRepeated) {
-
 
92
        Axis.ROW.setRepeated(getElement(), newRepeated);
-
 
93
        this.repeated = newRepeated;
79
        }
94
    }
-
 
95
 
-
 
96
    // plain Cell instances have multiple indexes (if repeated) but MutableCell are unique
-
 
97
    final int getX(MutableCell<D> c) {
-
 
98
        final int stop = this.getCellCount();
-
 
99
        for (int i = 0; i < stop; i++) {
-
 
100
            final Cell<D> item = this.cells[i];
-
 
101
            if (c.equals(item))
-
 
102
                return i;
-
 
103
        }
-
 
104
        return -1;
-
 
105
    }
-
 
106
 
-
 
107
    private void addCellElem(final Element cellElem, StyleDesc<CellStyle> cellStyleDesc) {
-
 
108
        final Cell<D> cell = new Cell<D>(this, cellElem, cellStyleDesc);
-
 
109
        final String repeatedS = cellElem.getAttributeValue("number-columns-repeated", this.getTABLE());
-
 
110
        final int toRepeat = StyleProperties.parseInt(repeatedS, 1);
-
 
111
        final int stop = this.cellCount + toRepeat;
-
 
112
        for (int i = this.cellCount; i < stop; i++) {
-
 
113
            this.cells[i] = cell;
-
 
114
        }
-
 
115
        this.cellCount = stop;
80
    }
116
    }
81
 
117
 
82
    /**
118
    /**
83
     * All cells of this row.
119
     * All cells of this row.
84
     * 
120
     * 
Line 88... Line 124...
88
    private List<Element> getCellElements() {
124
    private List<Element> getCellElements() {
89
        // seuls table-cell et covered-table-cell sont légaux
125
        // seuls table-cell et covered-table-cell sont légaux
90
        return this.getElement().getChildren();
126
        return this.getElement().getChildren();
91
    }
127
    }
92
 
128
 
-
 
129
    protected final int getCellCount() {
-
 
130
        return this.cellCount;
-
 
131
    }
-
 
132
 
-
 
133
    private final List<Cell<D>> getCellsAsList() {
-
 
134
        return Arrays.asList(this.cells);
-
 
135
    }
-
 
136
 
93
    protected final Cell<D> getCellAt(int col) {
137
    protected final Cell<D> getCellAt(int col) {
94
        return this.cells.get(col);
138
        return this.cells[col];
95
    }
139
    }
96
 
140
 
97
    protected final Cell<D> getValidCellAt(int col) {
141
    protected final Cell<D> getValidCellAt(int col) {
98
        final Cell<D> c = this.getCellAt(col);
142
        final Cell<D> c = this.getCellAt(col);
99
        if (!c.isValid())
143
        if (!c.isValid())
100
            throw new IllegalArgumentException("invalid cell " + c);
144
            throw new IllegalArgumentException("invalid cell " + c);
101
        return c;
145
        return c;
102
    }
146
    }
103
 
147
 
104
    public final MutableCell<D> getMutableCellAt(final int col) {
148
    public final MutableCell<D> getMutableCellAt(final int col) {
105
        final Cell c = this.getValidCellAt(col);
149
        final Cell<D> c = this.getValidCellAt(col);
106
        if (!(c instanceof MutableCell)) {
150
        if (!(c instanceof MutableCell)) {
107
            final Element element = c.getElement();
-
 
108
            final String repeatedS = element.getAttributeValue("number-columns-repeated", this.getSheet().getTABLE());
-
 
109
            if (repeatedS != null) {
-
 
110
                final int repeated = Integer.parseInt(repeatedS);
-
 
111
                final int firstIndex = this.cells.indexOf(c);
-
 
112
                final int lastIndex = firstIndex + repeated - 1;
-
 
113
 
-
 
114
                final int preRepeated = col - firstIndex;
-
 
115
                final int postRepeated = lastIndex - col;
-
 
116
 
-
 
117
                casse(element, firstIndex, preRepeated, true);
-
 
118
                element.removeAttribute("number-columns-repeated", this.getSheet().getTABLE());
151
            RepeatedBreaker.<D> getCellBreaker().breakRepeated(this, getCellsAsList(), col);
119
                casse(element, col + 1, postRepeated, false);
-
 
120
            }
-
 
121
            this.cells.set(col, new MutableCell<D>(this, element));
-
 
122
        }
152
        }
123
        return (MutableCell<D>) this.getValidCellAt(col);
153
        return (MutableCell<D>) this.getValidCellAt(col);
124
    }
154
    }
125
 
155
 
126
    private final void casse(Element element, int firstIndex, int repeat, boolean before) {
-
 
127
        if (repeat > 0) {
-
 
128
            final Element newElem = (Element) element.clone();
-
 
129
            element.getParentElement().addContent(element.getParent().indexOf(element) + (before ? 0 : 1), newElem);
-
 
130
            newElem.setAttribute("number-columns-repeated", repeat + "", this.getSheet().getTABLE());
-
 
131
            final Cell<D> preCell = new Cell<D>(this, newElem);
-
 
132
            for (int i = 0; i < repeat; i++) {
-
 
133
                this.cells.set(firstIndex + i, preCell);
-
 
134
            }
-
 
135
        }
-
 
136
    }
-
 
137
 
-
 
138
    // rempli cette ligne avec autant de cellules vides qu'il faut
156
    // rempli cette ligne avec autant de cellules vides qu'il faut
139
    void columnCountChanged() {
157
    void columnCountChanged(StyleStyleDesc<CellStyle> cellStyleDesc) {
140
        final int diff = this.getSheet().getColumnCount() - this.cells.size();
158
        final int diff = this.getSheet().getColumnCount() - getCellCount();
141
        if (diff < 0) {
159
        if (diff < 0) {
142
            throw new IllegalStateException("should have used Table.removeColumn()");
160
            throw new IllegalStateException("should have used Table.removeColumn()");
143
        } else if (diff > 0) {
161
        } else if (diff > 0) {
144
            final Element e = Cell.createEmpty(this.getSheet().getODDocument().getVersion(), diff);
162
            final Element e = Cell.createEmpty(this.getSheet().getODDocument().getVersion(), diff);
145
            this.getElement().addContent(e);
163
            this.getElement().addContent(e);
-
 
164
            this.ensureRoom(diff);
146
            addCellElem(e);
165
            addCellElem(e, cellStyleDesc);
147
        }
166
        }
148
        if (this.cells.size() != this.getSheet().getColumnCount())
167
        assert this.getCellCount() == this.getSheet().getColumnCount();
149
            throw new IllegalStateException();
-
 
150
    }
168
    }
151
 
169
 
152
    void checkRemove(int firstIndex, int lastIndexExcl) {
170
    void checkRemove(int firstIndex, int lastIndexExcl) {
153
        if (lastIndexExcl > this.cells.size()) {
171
        if (lastIndexExcl > getCellCount()) {
154
            throw new IndexOutOfBoundsException(lastIndexExcl + " > " + this.cells.size());
172
            throw new IndexOutOfBoundsException(lastIndexExcl + " > " + getCellCount());
155
        }
173
        }
156
        if (!this.getCellAt(firstIndex).isValid())
174
        if (!this.getCellAt(firstIndex).isValid())
157
            throw new IllegalArgumentException("unable to remove covered cell at " + firstIndex);
175
            throw new IllegalArgumentException("unable to remove covered cell at " + firstIndex);
158
    }
176
    }
159
 
177
 
-
 
178
    // ATTN unsafe, must call checkRemove() first
160
    void removeCells(int firstIndex, int lastIndexExcl) {
179
    void removeCells(int firstIndex, int lastIndexExcl) {
161
        checkRemove(firstIndex, lastIndexExcl);
-
 
162
 
-
 
163
        this.getMutableCellAt(firstIndex).unmerge();
180
        this.getMutableCellAt(firstIndex).unmerge();
164
 
181
 
165
        // if lastIndex == size, nothing to do
182
        // if lastIndex == size, nothing to do
166
        if (lastIndexExcl < this.cells.size()) {
183
        if (lastIndexExcl < getCellCount()) {
167
            if (!this.getCellAt(lastIndexExcl - 1).isValid()) {
184
            if (!this.getCellAt(lastIndexExcl - 1).isValid()) {
168
                int currentCol = lastIndexExcl - 2;
185
                int currentCol = lastIndexExcl - 2;
169
                // the covering cell is on this row since last cells of previous rows have been
186
                // the covering cell is on this row since last cells of previous rows have been
170
                // unmerged (see *)
187
                // unmerged (see *)
171
                // we've just unmerged firstIndex so there must be a non covered cell before it
188
                // we've just unmerged firstIndex so there must be a non covered cell before it
Line 180... Line 197...
180
        }
197
        }
181
 
198
 
182
        for (int i = firstIndex; i < lastIndexExcl; i++) {
199
        for (int i = firstIndex; i < lastIndexExcl; i++) {
183
            // ok to detach multiple times the same element (since repeated cells share the same XML
200
            // ok to detach multiple times the same element (since repeated cells share the same XML
184
            // element)
201
            // element)
185
            this.cells.remove(firstIndex).getElement().detach();
202
            this.cells[firstIndex].getElement().detach();
186
        }
203
        }
-
 
204
        final int movedCount = getCellCount() - lastIndexExcl;
-
 
205
        System.arraycopy(this.cells, lastIndexExcl, this.cells, firstIndex, movedCount);
-
 
206
        this.cells = Arrays.copyOfRange(this.cells, 0, firstIndex + movedCount);
-
 
207
        this.cellCount = this.cells.length;
-
 
208
        assert this.getCellCount() == this.getSheet().getColumnCount();
187
    }
209
    }
188
 
210
 
189
}
211
}