svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / layout / mapbox / model / MapBoxModel.java @ 1714
History | View | Annotate | Download (32.7 KB)
1 | 1714 | fdiaz | /*
|
---|---|---|---|
2 | * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||
3 | * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||
4 | */
|
||
5 | package org.gvsig.layout.mapbox.model; |
||
6 | |||
7 | import java.awt.Rectangle; |
||
8 | import java.awt.geom.Dimension2D; |
||
9 | import java.awt.geom.Point2D; |
||
10 | import java.awt.geom.Rectangle2D; |
||
11 | import java.util.ArrayList; |
||
12 | import java.util.Collections; |
||
13 | import java.util.HashSet; |
||
14 | import java.util.Iterator; |
||
15 | import java.util.List; |
||
16 | import java.util.Objects; |
||
17 | import java.util.Set; |
||
18 | import org.apache.commons.lang3.tuple.ImmutablePair; |
||
19 | import org.apache.commons.lang3.tuple.Pair; |
||
20 | import org.apache.commons.math.util.MathUtils; |
||
21 | import static org.gvsig.layout.mapbox.fframe.FFrameMapBox.MAPBOX_EPSILON; |
||
22 | import org.gvsig.tools.ToolsLocator; |
||
23 | import org.gvsig.tools.dynobject.DynStruct; |
||
24 | import org.gvsig.tools.lang.CloneableUtils; |
||
25 | import org.gvsig.tools.persistence.PersistenceManager; |
||
26 | import org.gvsig.tools.persistence.Persistent; |
||
27 | import org.gvsig.tools.persistence.PersistentState; |
||
28 | import org.gvsig.tools.persistence.exception.PersistenceException; |
||
29 | import org.gvsig.tools.util.IsEmpty; |
||
30 | import org.slf4j.Logger; |
||
31 | import org.slf4j.LoggerFactory; |
||
32 | |||
33 | /**
|
||
34 | *
|
||
35 | * @author fdiaz
|
||
36 | */
|
||
37 | public class MapBoxModel implements IsEmpty, Persistent, org.gvsig.tools.lang.Cloneable { |
||
38 | |||
39 | private static final Logger LOGGER = LoggerFactory.getLogger(MapBoxModel.class); |
||
40 | |||
41 | public static final String PERSISTENCE_DEFINITION_NAME = "MapBoxModel"; |
||
42 | |||
43 | public static final int POSITION_OUT_OF_MAPBOX = -1; |
||
44 | public static final int POSITION_IN_CELL = 0; |
||
45 | public static final int POSITION_AT_TOP_OF_CELL = 1; |
||
46 | public static final int POSITION_AT_BOTOM_OF_CELL = 2; |
||
47 | public static final int POSITION_ON_LEFT_EDGE_OF_CELL = 3; |
||
48 | public static final int POSITION_ON_RIGHT_EDGE_OF_CELL = 4; |
||
49 | |||
50 | private List<Cell> cells; |
||
51 | private Dimension2D dimension; |
||
52 | |||
53 | public MapBoxModel() {
|
||
54 | this.cells = new ArrayList<>(); |
||
55 | } |
||
56 | |||
57 | public MapBoxModel(Dimension2D dimension, int columns, int rows) { |
||
58 | this();
|
||
59 | this.dimension = dimension;
|
||
60 | |||
61 | double cellWidth = dimension.getWidth()/columns;
|
||
62 | double cellHeight = dimension.getHeight()/rows;
|
||
63 | for (int i = 0; i < columns; i++) { |
||
64 | for (int j = 0; j < rows; j++) { |
||
65 | cells.add(new CellImpl(i*cellWidth, j*cellHeight, cellWidth, cellHeight));
|
||
66 | } |
||
67 | } |
||
68 | } |
||
69 | |||
70 | public MapBoxModel(Dimension2D dimension, List<Cell> cells) { |
||
71 | this();
|
||
72 | this.dimension = dimension;
|
||
73 | |||
74 | for (Cell cell : cells) {
|
||
75 | this.cells.add(cell);
|
||
76 | } |
||
77 | } |
||
78 | |||
79 | public Cell getCell(double x, double y) { |
||
80 | for (Cell cell : cells) {
|
||
81 | if(cell.contains(x, y)){
|
||
82 | return cell;
|
||
83 | } |
||
84 | } |
||
85 | return null; |
||
86 | } |
||
87 | |||
88 | public List<Cell> getCells() { |
||
89 | return cells;
|
||
90 | } |
||
91 | |||
92 | public List<Cell> getCells(Rectangle2D r) { |
||
93 | List<Cell> res = new ArrayList(); |
||
94 | for (Cell cell : cells) {
|
||
95 | if(cell.isContained(r)) { // || cell.intersects(r)){ |
||
96 | res.add(cell); |
||
97 | } |
||
98 | } |
||
99 | return res;
|
||
100 | |||
101 | } |
||
102 | |||
103 | public void add(Cell c) { |
||
104 | this.cells.add(c);
|
||
105 | } |
||
106 | |||
107 | public void insertRow(Cell cell) { |
||
108 | try {
|
||
109 | Dimension2D oldDimension = (Dimension2D)(this.dimension.clone()); |
||
110 | double y = cell.getY();
|
||
111 | /* Obtenemos las celdas a las que pertenece la celda del par?metro
|
||
112 | para obtener la altura de la fila que ser? la menor altura
|
||
113 | de todas las de la misma fila
|
||
114 | */
|
||
115 | List<Cell> sameRowCells = getRowCells(y);
|
||
116 | double rowHeight = Double.POSITIVE_INFINITY; |
||
117 | for (Cell sameRowCell : sameRowCells) {
|
||
118 | if(sameRowCell.getHeight()<rowHeight){
|
||
119 | rowHeight = sameRowCell.getHeight(); |
||
120 | } |
||
121 | } |
||
122 | |||
123 | // Obtenemos todas las celdas que est?n debajo de donde tenemos que a?adir una fila nueva
|
||
124 | List<Cell> nextRowsCells = getNextRowsCells(y);
|
||
125 | |||
126 | // Obtenemos todas las celdas que est?n atravesadas por la l?nea horizontal de donde tenemos que a?adir una fila nueva
|
||
127 | List<Cell> rowTraversedCells = getTraversedRowCells(y);
|
||
128 | |||
129 | List<Cell> visited = new ArrayList<>(); |
||
130 | // A?adimos las celdas de la fila nueva
|
||
131 | for (Cell curCell : sameRowCells) {
|
||
132 | Cell c = curCell.clone(); |
||
133 | c.setY(y); |
||
134 | c.setHeight(rowHeight); |
||
135 | this.add(c);
|
||
136 | visited.add(curCell); |
||
137 | } |
||
138 | |||
139 | // Movemos las celdas que deben estar debajo de la fila nueva
|
||
140 | for (Cell curCell : nextRowsCells) {
|
||
141 | curCell.setY(curCell.getY() + rowHeight); |
||
142 | visited.add(curCell); |
||
143 | } |
||
144 | |||
145 | // Ampliamos la altura de las celdas que son atravesadas por la l?nea horizontal de donde se ha a?adido la fila nueva
|
||
146 | for (Cell curCell : rowTraversedCells) {
|
||
147 | if(visited.contains(curCell)){
|
||
148 | continue;
|
||
149 | } |
||
150 | curCell.setHeight(curCell.getHeight()+ rowHeight); |
||
151 | } |
||
152 | this.dimension.setSize(dimension.getWidth(), dimension.getHeight() + rowHeight);
|
||
153 | resize(oldDimension); |
||
154 | } catch (Exception ex) { |
||
155 | LOGGER.warn("Can't insert row before cell "+Objects.toString(cell), ex);
|
||
156 | } |
||
157 | } |
||
158 | |||
159 | /**
|
||
160 | * Insert a column to the left of the cell column passed as a parameter
|
||
161 | *
|
||
162 | * @param cell
|
||
163 | */
|
||
164 | public void insertColumn(Cell cell) { |
||
165 | try {
|
||
166 | Dimension2D oldDimension = (Dimension2D)(this.dimension.clone()); |
||
167 | double x = cell.getX();
|
||
168 | /* Obtenemos las celdas de la columna a la que pertenece la celda del par?metro
|
||
169 | para obtener la anchura de la columna que ser? la menor anchura
|
||
170 | de todas las de la misma fila
|
||
171 | */
|
||
172 | List<Cell> sameColumnCells = getColumnCells(x);
|
||
173 | double rowWidth = Double.POSITIVE_INFINITY; |
||
174 | for (Cell sameColumnCell : sameColumnCells) {
|
||
175 | if(sameColumnCell.getWidth()<rowWidth){
|
||
176 | rowWidth = sameColumnCell.getWidth(); |
||
177 | } |
||
178 | } |
||
179 | |||
180 | // Obtenemos todas las celdas que est?n a la derecha de donde tenemos que a?adir la columna nueva
|
||
181 | List<Cell> nextColumnsCells = getNextColumnsCells(x);
|
||
182 | |||
183 | // Obtenemos todas las celdas que est?n atravesadas por la l?nea vertical de donde tenemos que a?adir la columna nueva
|
||
184 | List<Cell> columnTraversedCells = getTraversedColumnCells(x);
|
||
185 | |||
186 | List<Cell> visited = new ArrayList<>(); |
||
187 | // A?adimos las celdas de la fila nueva
|
||
188 | for (Cell curCell : sameColumnCells) {
|
||
189 | Cell c = (Cell) CloneableUtils.cloneQuietly(curCell); |
||
190 | c.setX(x); |
||
191 | c.setWidth(rowWidth); |
||
192 | this.add(c);
|
||
193 | visited.add(curCell); |
||
194 | } |
||
195 | |||
196 | // Movemos las celdas que deben estar a la derecha de la fila nueva
|
||
197 | for (Cell curCell : nextColumnsCells) {
|
||
198 | curCell.setX(curCell.getX() + rowWidth); |
||
199 | visited.add(curCell); |
||
200 | } |
||
201 | |||
202 | // Ampliamos la anchura de las celdas que son atravesadas por la l?nea vertical de donde se ha a?adido la columna nueva
|
||
203 | for (Cell curCell : columnTraversedCells) {
|
||
204 | if(visited.contains(curCell)){
|
||
205 | continue;
|
||
206 | } |
||
207 | curCell.setWidth(curCell.getWidth()+ rowWidth); |
||
208 | } |
||
209 | this.dimension.setSize(dimension.getWidth()+rowWidth, dimension.getHeight());
|
||
210 | resize(oldDimension); |
||
211 | } catch (Exception ex) { |
||
212 | LOGGER.warn("Can't insert column before cell "+Objects.toString(cell), ex);
|
||
213 | } |
||
214 | } |
||
215 | |||
216 | /**
|
||
217 | * Adds a row below the row to which the cell passed as a parameter belongs
|
||
218 | * @param cell
|
||
219 | */
|
||
220 | public void addRow(Cell cell) { |
||
221 | try {
|
||
222 | /* Nos guardamos la dimension del cajetin actual para devolversela al acabar */
|
||
223 | Dimension2D oldDimension = (Dimension2D)(this.dimension.clone()); |
||
224 | /* Obtenemos las celdas que est?n justo encima de donde tenemos que a?adir una fila nueva
|
||
225 | para obtener la altura de la fila que ser? la menor altura
|
||
226 | de todas las de la misma fila
|
||
227 | */
|
||
228 | double y = cell.getY() + cell.getHeight();
|
||
229 | List<Cell> previousRowCells = getPreviousRowCells(y);
|
||
230 | double rowHeight = Double.POSITIVE_INFINITY; |
||
231 | for (Cell previousRowCell : previousRowCells) {
|
||
232 | if(previousRowCell.getHeight()<rowHeight){
|
||
233 | rowHeight = previousRowCell.getHeight(); |
||
234 | } |
||
235 | } |
||
236 | |||
237 | // Obtenemos todas las celdas que est?n debajo de donde tenemos que a?adir una fila nueva
|
||
238 | List<Cell> nextRowsCells = getNextRowsCells(y);
|
||
239 | |||
240 | // Obtenemos todas las celdas que est?n atravesadas por la l?nea horizontal de donde tenemos que a?adir una fila nueva
|
||
241 | List<Cell> rowTraversedCells = getTraversedRowCells(y);
|
||
242 | |||
243 | List<Cell> visited = new ArrayList<>(); |
||
244 | // A?adimos las celdas de la fila nueva
|
||
245 | for (Cell curCell : previousRowCells) {
|
||
246 | Cell c = (Cell) CloneableUtils.cloneQuietly(curCell); |
||
247 | c.setY(y); |
||
248 | c.setHeight(rowHeight); |
||
249 | this.add(c);
|
||
250 | visited.add(curCell); |
||
251 | } |
||
252 | |||
253 | // Movemos las celdas que deben estar debajo de la fila nueva
|
||
254 | for (Cell curCell : nextRowsCells) {
|
||
255 | if(visited.contains(curCell)){
|
||
256 | continue;
|
||
257 | } |
||
258 | curCell.setY(curCell.getY() + rowHeight); |
||
259 | visited.add(curCell); |
||
260 | } |
||
261 | |||
262 | // Ampliamos la altura de las celdas que son atravesadas por la l?nea horizontal de donde se ha a?adido la fila nueva
|
||
263 | for (Cell curCell : rowTraversedCells) {
|
||
264 | if(visited.contains(curCell)){
|
||
265 | continue;
|
||
266 | } |
||
267 | curCell.setHeight(curCell.getHeight()+ rowHeight); |
||
268 | } |
||
269 | /*Recalculamos la dimension segun la fila a?adida*/
|
||
270 | this.dimension.setSize(dimension.getWidth(), dimension.getHeight() + rowHeight);
|
||
271 | |||
272 | /*Devolvemos la dimension que ten?a el cajet?n de manera proporcionada*/
|
||
273 | resize(oldDimension); |
||
274 | } catch (Exception ex) { |
||
275 | LOGGER.warn("Can't add row after cell "+Objects.toString(cell), ex);
|
||
276 | } |
||
277 | } |
||
278 | |||
279 | /**
|
||
280 | * Adds a column to the right of the cell column passed as a parameter
|
||
281 | * @param cell
|
||
282 | */
|
||
283 | public void addColumn(Cell cell) { |
||
284 | try {
|
||
285 | /* Nos guardamos la dimension del cajetin actual para devolversela al acabar */
|
||
286 | Dimension2D oldDimension = (Dimension2D)(this.dimension.clone()); |
||
287 | double x = cell.getX() + cell.getWidth();
|
||
288 | /* Obtenemos las celdas que est?n justo a la izquierda de donde tenemos que a?adir una fila nueva
|
||
289 | para obtener la anchura de la columna que ser? la menor anchura
|
||
290 | de todas las de la misma columna
|
||
291 | */
|
||
292 | List<Cell> previousColumnCells = getPreviousColumnCells(x);
|
||
293 | double columnWidth = Double.POSITIVE_INFINITY; |
||
294 | for (Cell previousColumnCell : previousColumnCells) {
|
||
295 | if(previousColumnCell.getWidth()<columnWidth){
|
||
296 | columnWidth = previousColumnCell.getWidth(); |
||
297 | } |
||
298 | } |
||
299 | |||
300 | // Obtenemos todas las celdas que est?n a la derecha de donde tenemos que a?adir una fila nueva
|
||
301 | List<Cell> nextColumnsCells = getNextColumnsCells(x);
|
||
302 | |||
303 | // Obtenemos todas las celdas que est?n atravesadas por la l?nea vertical de donde tenemos que a?adir la columna nueva
|
||
304 | List<Cell> columnTraversedCells = getTraversedColumnCells(cell.getX() + cell.getWidth());
|
||
305 | |||
306 | List<Cell> visited = new ArrayList<>(); |
||
307 | // A?adimos las celdas de la columna nueva
|
||
308 | for (Cell curCell : previousColumnCells) {
|
||
309 | Cell c = (Cell) CloneableUtils.cloneQuietly(curCell); |
||
310 | c.setX(x); |
||
311 | c.setWidth(columnWidth); |
||
312 | this.add(c);
|
||
313 | visited.add(curCell); |
||
314 | } |
||
315 | |||
316 | // Movemos las celdas que deben estar a la derecha de la columna nueva
|
||
317 | for (Cell curCell : nextColumnsCells) {
|
||
318 | if(visited.contains(curCell)){
|
||
319 | continue;
|
||
320 | } |
||
321 | curCell.setX(curCell.getX() + columnWidth); |
||
322 | visited.add(curCell); |
||
323 | } |
||
324 | |||
325 | // Ampliamos la anchura de las celdas que son atravesadas por la l?nea vertical de donde se ha a?adido la columna nueva
|
||
326 | for (Cell curCell : columnTraversedCells) {
|
||
327 | if(visited.contains(curCell)){
|
||
328 | continue;
|
||
329 | } |
||
330 | curCell.setWidth(curCell.getWidth()+columnWidth); |
||
331 | } |
||
332 | /*Recalculamos la dimension segun la columna a?adida*/
|
||
333 | this.dimension.setSize(dimension.getWidth()+columnWidth, dimension.getHeight());
|
||
334 | /*Devolvemos la dimension que ten?a el cajet?n de manera proporcionada*/
|
||
335 | resize(oldDimension); |
||
336 | } catch (Exception ex) { |
||
337 | LOGGER.warn("Can't insert column after cell "+Objects.toString(cell), ex);
|
||
338 | } |
||
339 | } |
||
340 | |||
341 | /**
|
||
342 | * Devuelve las celdas que empiezan en la l?nea horizontal en que est? a una altura y
|
||
343 | *
|
||
344 | * @param y
|
||
345 | * @return
|
||
346 | */
|
||
347 | private List<Cell> getRowCells(double y) { |
||
348 | List<Cell> res = new ArrayList<>(); |
||
349 | for (Cell cell : cells) {
|
||
350 | if(MathUtils.equals(cell.getY(),y,MAPBOX_EPSILON)) { //FIXME: entorno |
||
351 | res.add(cell); |
||
352 | } |
||
353 | } |
||
354 | return res;
|
||
355 | } |
||
356 | |||
357 | /**
|
||
358 | * Devuelve las celdas que empiezan en la l?nea horizontal en que est? a una altura y
|
||
359 | *
|
||
360 | * @param y
|
||
361 | * @return
|
||
362 | */
|
||
363 | private List<Cell> getRowCellsBetween(double y, double y1) { |
||
364 | Set<Cell> res = new HashSet(); |
||
365 | for (Cell cell : cells) {
|
||
366 | if (MathUtils.equals(cell.getY(), y, MAPBOX_EPSILON)
|
||
367 | && MathUtils.equals(cell.getY() + cell.getHeight(), y1, MAPBOX_EPSILON)) { |
||
368 | res.add(cell); |
||
369 | } |
||
370 | if (MathUtils.equals(cell.getY(), y, MAPBOX_EPSILON)
|
||
371 | && cell.getY() + cell.getHeight() < y1) { |
||
372 | res.add(cell); |
||
373 | } |
||
374 | if (MathUtils.equals(cell.getY() + cell.getHeight(), y1, MAPBOX_EPSILON)
|
||
375 | && cell.getY() > y) { |
||
376 | res.add(cell); |
||
377 | } |
||
378 | if(cell.getY() > y && cell.getY()+cell.getHeight() < y1) {
|
||
379 | res.add(cell); |
||
380 | } |
||
381 | |||
382 | } |
||
383 | return new ArrayList<>(res); |
||
384 | } |
||
385 | |||
386 | /**
|
||
387 | * Devuelve las celdas que empiezan debajo de la l?nea horizontal en que est? a una altura y
|
||
388 | *
|
||
389 | * @param y
|
||
390 | * @return
|
||
391 | */
|
||
392 | private List<Cell> getNextRowsCells(double y) { |
||
393 | List<Cell> res = new ArrayList<>(); |
||
394 | for (Cell cell : cells) {
|
||
395 | if(cell.getY() >= y || MathUtils.equals(cell.getY(),y,MAPBOX_EPSILON)) {
|
||
396 | res.add(cell); |
||
397 | } |
||
398 | } |
||
399 | return res;
|
||
400 | } |
||
401 | |||
402 | /**
|
||
403 | * Devuelve las celdas que terminan en la l?nea horizontal que est? a una altura y
|
||
404 | *
|
||
405 | * @param y
|
||
406 | * @return
|
||
407 | */
|
||
408 | private List<Cell> getPreviousRowCells(double y) { |
||
409 | List<Cell> res = new ArrayList<>(); |
||
410 | for (Cell cell : cells) {
|
||
411 | if(MathUtils.equals(cell.getY()+cell.getHeight(),y,MAPBOX_EPSILON)) {
|
||
412 | res.add(cell); |
||
413 | } |
||
414 | } |
||
415 | return res;
|
||
416 | } |
||
417 | |||
418 | /**
|
||
419 | * Devuelve las celdas que son atravesadas por la l?nea horizontal que est? a una altura y
|
||
420 | *
|
||
421 | * @param y
|
||
422 | * @return
|
||
423 | */
|
||
424 | private List<Cell> getTraversedRowCells(double y) { |
||
425 | List<Cell> res = new ArrayList<>(); |
||
426 | for (Cell cell : cells) {
|
||
427 | if(cell.getY() < y && cell.getY()+cell.getHeight() > y) {
|
||
428 | res.add(cell); |
||
429 | } |
||
430 | } |
||
431 | return res;
|
||
432 | } |
||
433 | |||
434 | /**
|
||
435 | * Devuelve las celdas que empiezan en la l?nea vertical que est? a una distancia x del origen
|
||
436 | *
|
||
437 | * @param y
|
||
438 | * @return
|
||
439 | */
|
||
440 | private List<Cell> getColumnCells(double x) { |
||
441 | List<Cell> res = new ArrayList<>(); |
||
442 | for (Cell cell : cells) {
|
||
443 | if(MathUtils.equals(cell.getX(),x,MAPBOX_EPSILON)) {
|
||
444 | res.add(cell); |
||
445 | } |
||
446 | } |
||
447 | return res;
|
||
448 | } |
||
449 | |||
450 | /**
|
||
451 | * Devuelve las celdas que empiezan en la l?nea horizontal en que est? a una altura y
|
||
452 | *
|
||
453 | * @param x
|
||
454 | * @return
|
||
455 | */
|
||
456 | private List<Cell> getColumnCellsBetween(double x, double x1) { |
||
457 | Set<Cell> res = new HashSet(); |
||
458 | for (Cell cell : cells) {
|
||
459 | if(MathUtils.equals(cell.getX(),x,MAPBOX_EPSILON) &&
|
||
460 | MathUtils.equals(cell.getX()+cell.getWidth(),x1,MAPBOX_EPSILON)) { |
||
461 | res.add(cell); |
||
462 | } |
||
463 | if(MathUtils.equals(cell.getX(),x,MAPBOX_EPSILON) &&
|
||
464 | cell.getX()+cell.getWidth()< x1) { |
||
465 | res.add(cell); |
||
466 | } |
||
467 | if(MathUtils.equals(cell.getX()+cell.getWidth(),x1,MAPBOX_EPSILON)&&
|
||
468 | cell.getX() > x) { |
||
469 | res.add(cell); |
||
470 | } |
||
471 | if(cell.getX() > x && cell.getX()+cell.getWidth() < x1) {
|
||
472 | res.add(cell); |
||
473 | } |
||
474 | |||
475 | } |
||
476 | return new ArrayList<>(res); |
||
477 | } |
||
478 | |||
479 | |||
480 | /**
|
||
481 | * Devuelve las celdas que empiezan m?s all? de la l?nea vertical que est? a una distancia x del origen
|
||
482 | *
|
||
483 | * @param y
|
||
484 | * @return
|
||
485 | */
|
||
486 | private List<Cell> getNextColumnsCells(double x) { |
||
487 | List<Cell> res = new ArrayList<>(); |
||
488 | for (Cell cell : cells) {
|
||
489 | if(cell.getX() >= x || MathUtils.equals(cell.getX(),x,MAPBOX_EPSILON)) {
|
||
490 | res.add(cell); |
||
491 | } |
||
492 | } |
||
493 | return res;
|
||
494 | } |
||
495 | |||
496 | /**
|
||
497 | * Devuelve las celdas que terminan en la l?nea vertical que est? a una distancia x del origen
|
||
498 | *
|
||
499 | * @param y
|
||
500 | * @return
|
||
501 | */
|
||
502 | private List<Cell> getPreviousColumnCells(double x) { |
||
503 | List<Cell> res = new ArrayList<>(); |
||
504 | for (Cell cell : cells) {
|
||
505 | if(MathUtils.equals(cell.getX()+cell.getWidth(),x,MAPBOX_EPSILON)) {
|
||
506 | res.add(cell); |
||
507 | } |
||
508 | } |
||
509 | return res;
|
||
510 | } |
||
511 | |||
512 | /**
|
||
513 | * Devuelve las celdas que son atravesadas por la l?nea vertical que est? a una distancia x del origen
|
||
514 | *
|
||
515 | * @param y
|
||
516 | * @return
|
||
517 | */
|
||
518 | private List<Cell> getTraversedColumnCells(double x) { |
||
519 | List<Cell> res = new ArrayList<>(); |
||
520 | for (Cell cell : cells) {
|
||
521 | if(cell.getX() < x && cell.getX()+cell.getWidth() > x) {
|
||
522 | res.add(cell); |
||
523 | } |
||
524 | } |
||
525 | return res;
|
||
526 | } |
||
527 | |||
528 | public void dump(List<Cell> theCells) { |
||
529 | if(theCells == null){ |
||
530 | theCells = cells; |
||
531 | } |
||
532 | for (Cell cell : theCells) {
|
||
533 | System.out.println(cell.toString());
|
||
534 | } |
||
535 | } |
||
536 | |||
537 | public void sort() { |
||
538 | Collections.sort(cells, (Cell o1, Cell o2) -> {
|
||
539 | int res = Double.compare(o1.getY(), o2.getY()); |
||
540 | if(res == 0){ |
||
541 | res = Double.compare(o1.getX(), o2.getX());
|
||
542 | } |
||
543 | return res;
|
||
544 | }); |
||
545 | } |
||
546 | |||
547 | public Cell join(List<Cell> theCells) { |
||
548 | Cell join = (Cell) CloneableUtils.cloneQuietly(theCells.get(0));
|
||
549 | for (Cell theCell : theCells) {
|
||
550 | join.join(theCell); |
||
551 | } |
||
552 | return join;
|
||
553 | } |
||
554 | |||
555 | public void combine(List<Cell> theCells) { |
||
556 | Cell join = join(theCells); |
||
557 | if(join == null) { |
||
558 | return;
|
||
559 | } |
||
560 | removeCells(theCells); |
||
561 | cells.add(join); |
||
562 | } |
||
563 | |||
564 | public void splitCellHorizontally(Cell theCell) { |
||
565 | double h = theCell.getHeight() / 2; |
||
566 | theCell.setHeight(h); |
||
567 | Cell cloned = (Cell) CloneableUtils.cloneQuietly(theCell); |
||
568 | cloned.setY(theCell.getY() + h); |
||
569 | cells.add(cloned); |
||
570 | } |
||
571 | |||
572 | public void splitCellsHorizontally(List<Cell> theCells) { |
||
573 | for (Cell theCell : theCells) {
|
||
574 | splitCellHorizontally(theCell); |
||
575 | } |
||
576 | } |
||
577 | |||
578 | public void splitCellVertically(Cell theCell) { |
||
579 | double w = theCell.getWidth() / 2; |
||
580 | theCell.setWidth(w); |
||
581 | Cell cloned = (Cell) CloneableUtils.cloneQuietly(theCell); |
||
582 | cloned.setX(theCell.getX() + w); |
||
583 | cells.add(cloned); |
||
584 | } |
||
585 | |||
586 | public void splitCellsVertically(List<Cell> theCells) { |
||
587 | for (Cell theCell : theCells) {
|
||
588 | splitCellVertically(theCell); |
||
589 | } |
||
590 | } |
||
591 | |||
592 | public void removeCells(List<Cell> theCells) { |
||
593 | cells.removeAll(theCells); |
||
594 | } |
||
595 | |||
596 | public void removeCells(Rectangle r) { |
||
597 | for (Iterator<Cell> iterator = cells.iterator(); iterator.hasNext();) { |
||
598 | Cell cell = iterator.next(); |
||
599 | if(cell.isContained(r)) { // || cell.intersects(r)){ |
||
600 | iterator.remove(); |
||
601 | } |
||
602 | } |
||
603 | } |
||
604 | |||
605 | public void removeColumn(Cell cell) { |
||
606 | /* Nos guardamos la dimension del cajetin actual para devolversela al acabar */
|
||
607 | Dimension2D oldDimension = (Dimension2D)(this.dimension.clone()); |
||
608 | |||
609 | double x = cell.getX();
|
||
610 | double columnWidth = cell.getWidth();
|
||
611 | List<Cell> columnCells = getColumnCellsBetween(x, x+columnWidth);
|
||
612 | List<Cell> nextColumnsCells = getNextColumnsCells(cell.getX()+cell.getWidth());
|
||
613 | List<Cell> leftTraversedColumnsCells = getTraversedColumnCells(cell.getX());
|
||
614 | List<Cell> rightTraversedColumnsCells = getTraversedColumnCells(cell.getX()+cell.getWidth());
|
||
615 | List<Cell> visited = new ArrayList<>(); |
||
616 | for (Cell columnCell : columnCells) {
|
||
617 | cells.remove(columnCell); |
||
618 | visited.add(columnCell); |
||
619 | } |
||
620 | for (Cell nextColumnsCell : nextColumnsCells) {
|
||
621 | if(visited.contains(nextColumnsCell)){
|
||
622 | continue;
|
||
623 | } |
||
624 | nextColumnsCell.setX(nextColumnsCell.getX()-columnWidth); |
||
625 | visited.add(nextColumnsCell); |
||
626 | } |
||
627 | for (Cell leftTraversedColumnsCell : leftTraversedColumnsCells) {
|
||
628 | if(visited.contains(leftTraversedColumnsCell)){
|
||
629 | continue;
|
||
630 | } |
||
631 | if(rightTraversedColumnsCells.contains(leftTraversedColumnsCell)){
|
||
632 | leftTraversedColumnsCell.setWidth(leftTraversedColumnsCell.getWidth()-columnWidth); |
||
633 | } else {
|
||
634 | leftTraversedColumnsCell.setWidth(x-leftTraversedColumnsCell.getX()); |
||
635 | } |
||
636 | visited.add(leftTraversedColumnsCell); |
||
637 | } |
||
638 | for (Cell rightTraversedColumnsCell : rightTraversedColumnsCells) {
|
||
639 | if(visited.contains(rightTraversedColumnsCell)){
|
||
640 | continue;
|
||
641 | } |
||
642 | rightTraversedColumnsCell.setWidth(rightTraversedColumnsCell.getX()+rightTraversedColumnsCell.getWidth()-(x+columnWidth)); |
||
643 | rightTraversedColumnsCell.setY(x+columnWidth); |
||
644 | } |
||
645 | /*Recalculamos la dimension segun la columna a?adida*/
|
||
646 | this.dimension.setSize(dimension.getWidth()-columnWidth, dimension.getHeight());
|
||
647 | /*Devolvemos la dimension que ten?a el cajet?n de manera proporcionada*/
|
||
648 | resize(oldDimension); |
||
649 | } |
||
650 | |||
651 | public void removeRow(Cell cell) { |
||
652 | /* Nos guardamos la dimension del cajetin actual para devolversela al acabar */
|
||
653 | Dimension2D oldDimension = (Dimension2D)(this.dimension.clone()); |
||
654 | double y = cell.getY();
|
||
655 | double rowHeight = cell.getHeight();
|
||
656 | List<Cell> rowCells = getRowCellsBetween(y, y+rowHeight);
|
||
657 | List<Cell> nextRowsCells = getNextRowsCells(cell.getY()+cell.getHeight());
|
||
658 | List<Cell> upTraversedRowsCells = getTraversedRowCells(cell.getY());
|
||
659 | List<Cell> downTraversedRowsCells = getTraversedRowCells(cell.getY()+cell.getHeight());
|
||
660 | List<Cell> visited = new ArrayList<>(); |
||
661 | for (Cell rowCell : rowCells) {
|
||
662 | cells.remove(rowCell); |
||
663 | visited.add(rowCell); |
||
664 | } |
||
665 | for (Cell nextRowsCell : nextRowsCells) {
|
||
666 | if(visited.contains(nextRowsCell)){
|
||
667 | continue;
|
||
668 | } |
||
669 | nextRowsCell.setY(nextRowsCell.getY()-rowHeight); |
||
670 | visited.add(nextRowsCell); |
||
671 | } |
||
672 | for (Cell upTraversedRowsCell : upTraversedRowsCells) {
|
||
673 | if(visited.contains(upTraversedRowsCell)){
|
||
674 | continue;
|
||
675 | } |
||
676 | if(downTraversedRowsCells.contains(upTraversedRowsCell)){
|
||
677 | upTraversedRowsCell.setHeight(upTraversedRowsCell.getHeight()-rowHeight); |
||
678 | } else {
|
||
679 | upTraversedRowsCell.setHeight(y-upTraversedRowsCell.getY()); |
||
680 | } |
||
681 | visited.add(upTraversedRowsCell); |
||
682 | } |
||
683 | for (Cell downTraversedRowsCell : downTraversedRowsCells) {
|
||
684 | if(visited.contains(downTraversedRowsCell)){
|
||
685 | continue;
|
||
686 | } |
||
687 | downTraversedRowsCell.setHeight(downTraversedRowsCell.getY()+downTraversedRowsCell.getHeight()-(y+rowHeight)); |
||
688 | downTraversedRowsCell.setY(y+rowHeight); |
||
689 | } |
||
690 | /*Recalculamos la dimension segun la fila borrada*/
|
||
691 | this.dimension.setSize(dimension.getWidth(), dimension.getHeight() - rowHeight);
|
||
692 | /*Devolvemos la dimension que ten?a el cajet?n de manera proporcionada*/
|
||
693 | resize(oldDimension); |
||
694 | |||
695 | } |
||
696 | |||
697 | public void resize(Dimension2D dimension){ |
||
698 | if (this.dimension != null) { |
||
699 | double scaleX = dimension.getWidth() / this.dimension.getWidth(); |
||
700 | double scaleY = dimension.getHeight() / this.dimension.getHeight(); |
||
701 | for (Cell cell : cells) {
|
||
702 | cell.setWidth(cell.getWidth() * scaleX); |
||
703 | cell.setHeight(cell.getHeight() * scaleY); |
||
704 | cell.setX(cell.getX() * scaleX); |
||
705 | cell.setY(cell.getY() * scaleY); |
||
706 | } |
||
707 | } |
||
708 | this.dimension = dimension;
|
||
709 | } |
||
710 | |||
711 | @Override
|
||
712 | public boolean isEmpty() { |
||
713 | return this.cells.isEmpty(); |
||
714 | } |
||
715 | |||
716 | public Pair<Integer, Cell> getRelativePosition(Point2D p, double tolerance) { |
||
717 | for (Cell cell : cells) {
|
||
718 | if(Math.abs(cell.getX()-p.getX())<=tolerance){ |
||
719 | return new ImmutablePair<>(POSITION_ON_LEFT_EDGE_OF_CELL, cell); |
||
720 | } |
||
721 | if(Math.abs(cell.getY()-p.getY())<=tolerance){ |
||
722 | return new ImmutablePair<>(POSITION_AT_TOP_OF_CELL, cell); |
||
723 | } |
||
724 | if(Math.abs(cell.getX()+cell.getWidth()-p.getX())<=tolerance){ |
||
725 | return new ImmutablePair<>(POSITION_ON_RIGHT_EDGE_OF_CELL, cell); |
||
726 | } |
||
727 | if(Math.abs(cell.getY()+cell.getHeight()-p.getY())<=tolerance){ |
||
728 | return new ImmutablePair<>(POSITION_AT_BOTOM_OF_CELL, cell); |
||
729 | } |
||
730 | if(cell.getRectangle().contains(p)){
|
||
731 | return new ImmutablePair<>(POSITION_IN_CELL, cell); |
||
732 | } |
||
733 | } |
||
734 | return new ImmutablePair<>(POSITION_OUT_OF_MAPBOX, null); |
||
735 | } |
||
736 | |||
737 | public void moveVerticalLine(double x0, double x1){ |
||
738 | List<Cell> columnCells = getColumnCells(x0);
|
||
739 | double maxX = Double.POSITIVE_INFINITY; |
||
740 | for (Cell columnCell : columnCells) {
|
||
741 | maxX = Math.min(columnCell.getX()+columnCell.getWidth(), maxX);
|
||
742 | } |
||
743 | List<Cell> previousColumnCells = getPreviousColumnCells(x0);
|
||
744 | double minX = Double.NEGATIVE_INFINITY; |
||
745 | for (Cell previousColumnCell : previousColumnCells) {
|
||
746 | minX = Math.max(previousColumnCell.getX(), minX);
|
||
747 | } |
||
748 | if(x1 < minX){
|
||
749 | throw new IllegalArgumentException("The line cannot be moved beyond the previous cell"); |
||
750 | } |
||
751 | if(x1 > maxX){
|
||
752 | throw new IllegalArgumentException("The line cannot be moved beyond the next cell"); |
||
753 | } |
||
754 | |||
755 | if(MathUtils.equals(x0, 0d, MAPBOX_EPSILON)) { //Primera l?nea afecta a la dimensi?n del cajet?n |
||
756 | for (Cell cell : cells) {
|
||
757 | if(cell.getX() == 0d){ |
||
758 | cell.setWidth(cell.getWidth()-x1); |
||
759 | } else {
|
||
760 | cell.setX(cell.getX()-x1); |
||
761 | } |
||
762 | } |
||
763 | this.dimension.setSize(this.dimension.getWidth()-(x1-x0), this.dimension.getHeight()); |
||
764 | |||
765 | } else if(MathUtils.equals(x0,dimension.getWidth(),MAPBOX_EPSILON)) { //Ultima l?nea afecta a la dimensi?n del cajet?n |
||
766 | for (Cell previousColumnCell : previousColumnCells) {
|
||
767 | previousColumnCell.setWidth(x1-previousColumnCell.getX()); |
||
768 | } |
||
769 | this.dimension.setSize(this.dimension.getWidth()+(x1-x0), this.dimension.getHeight()); |
||
770 | |||
771 | } else { //No afecta a la dimensi?n del cajet?n |
||
772 | for (Cell previousColumnCell : previousColumnCells) {
|
||
773 | previousColumnCell.setWidth(x1-previousColumnCell.getX()); |
||
774 | } |
||
775 | for (Cell columnCell : columnCells) {
|
||
776 | columnCell.setX(x1); |
||
777 | columnCell.setWidth(columnCell.getWidth()-(x1-x0)); |
||
778 | } |
||
779 | } |
||
780 | } |
||
781 | |||
782 | public void moveHorizontalLine(double y0, double y1){ |
||
783 | List<Cell> rowCells = getRowCells(y0);
|
||
784 | double maxY = Double.POSITIVE_INFINITY; |
||
785 | for (Cell rowCell : rowCells) {
|
||
786 | maxY = Math.min(rowCell.getY()+rowCell.getHeight(), maxY);
|
||
787 | } |
||
788 | List<Cell> previousRowCells = getPreviousRowCells(y0);
|
||
789 | double minY = Double.NEGATIVE_INFINITY; |
||
790 | for (Cell previousRowCell : previousRowCells) {
|
||
791 | minY = Math.max(previousRowCell.getY(), minY);
|
||
792 | } |
||
793 | if(y1 < minY){
|
||
794 | throw new IllegalArgumentException("The line cannot be moved beyond the previous cell"); |
||
795 | } |
||
796 | if(y1 > maxY){
|
||
797 | throw new IllegalArgumentException("The line cannot be moved beyond the next cell"); |
||
798 | } |
||
799 | |||
800 | if(MathUtils.equals(y0,0d,MAPBOX_EPSILON)) { //Primera l?nea afecta a la dimensi?n del cajet?n |
||
801 | for (Cell cell : cells) {
|
||
802 | if(cell.getY() == 0d){ |
||
803 | cell.setHeight(cell.getHeight()-y1); |
||
804 | } else {
|
||
805 | cell.setY(cell.getY()-y1); |
||
806 | } |
||
807 | } |
||
808 | this.dimension.setSize(this.dimension.getWidth(), this.dimension.getHeight()-(y1-y0)); |
||
809 | } else if(MathUtils.equals(y0,dimension.getHeight(),MAPBOX_EPSILON)) { //Ultima l?nea afecta a la dimensi?n del cajet?n |
||
810 | for (Cell previousRowCell : previousRowCells) {
|
||
811 | previousRowCell.setHeight(y1-previousRowCell.getY()); |
||
812 | } |
||
813 | this.dimension.setSize(this.dimension.getWidth(), this.dimension.getHeight()+(y1-y0)); |
||
814 | |||
815 | } else { //No afecta a la dimensi?n del cajet?n |
||
816 | for (Cell previousRowCell : previousRowCells) {
|
||
817 | previousRowCell.setHeight(y1-previousRowCell.getY()); |
||
818 | } |
||
819 | for (Cell rowCell : rowCells) {
|
||
820 | rowCell.setY(y1); |
||
821 | rowCell.setHeight(rowCell.getHeight()-(y1-y0)); |
||
822 | } |
||
823 | } |
||
824 | } |
||
825 | |||
826 | @Override
|
||
827 | public Object clone() throws CloneNotSupportedException { |
||
828 | MapBoxModel other = (MapBoxModel) super.clone();
|
||
829 | |||
830 | List<Cell> clonedCells = new ArrayList<>(); |
||
831 | for (Cell cell : cells) {
|
||
832 | clonedCells.add(cell.clone()); |
||
833 | } |
||
834 | other.cells = clonedCells; |
||
835 | if(this.dimension != null){ |
||
836 | other.dimension = (Dimension2D) this.dimension.clone(); |
||
837 | } |
||
838 | return other;
|
||
839 | } |
||
840 | |||
841 | public static void registerPersistent() { |
||
842 | PersistenceManager manager = ToolsLocator.getPersistenceManager(); |
||
843 | if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) { |
||
844 | DynStruct definition = |
||
845 | manager.addDefinition(MapBoxModel.class, |
||
846 | PERSISTENCE_DEFINITION_NAME, |
||
847 | "FFrameMapBox persistence definition", null, null); |
||
848 | |||
849 | definition.addDynFieldList("cells").setClassOfItems(Cell.class).setMandatory(true); |
||
850 | definition.addDynFieldDouble("width").setMandatory(true); |
||
851 | definition.addDynFieldDouble("height").setMandatory(true); |
||
852 | } |
||
853 | } |
||
854 | |||
855 | @Override
|
||
856 | public void loadFromState(PersistentState state) |
||
857 | throws PersistenceException {
|
||
858 | List<Cell> c = state.getList("cells"); |
||
859 | if(c!=null){ |
||
860 | this.cells = new ArrayList<>(c); |
||
861 | } |
||
862 | double width = state.getDouble("width"); |
||
863 | double height = state.getDouble("height"); |
||
864 | this.dimension = new Dimension2DDouble(width, height); |
||
865 | } |
||
866 | |||
867 | @Override
|
||
868 | public void saveToState(PersistentState state) throws PersistenceException { |
||
869 | state.set("cells", this.cells); |
||
870 | state.set("width", this.dimension.getWidth()); |
||
871 | state.set("height", this.dimension.getHeight()); |
||
872 | } |
||
873 | |||
874 | } |