KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > layout > PortletBeanSpanningGrid


1 package org.jahia.layout;
2
3 /**
4  * Title: Extension of PortletBeanGrid to handle HTML-like spanning
5  * Description: This class extends on the simple grid by allowing grid entries
6  * to span multiple columns or multiple rows, just as HTML tables may. This mostly
7  * has consequences on the various iterators, on addition of elements in the
8  * table, and moving elements throughout the grid
9  * Copyright: Copyright (c) 2002
10  * Company: Jahia Ltd
11  * @author Serge Huber
12  * @version 1.0
13  * @todo not entirely implemented yet...
14  */

15
16 import java.util.Enumeration JavaDoc;
17 import java.util.Vector JavaDoc;
18
19 import org.jahia.exceptions.JahiaException;
20 import org.jahia.utils.JahiaConsole;
21
22 public class PortletBeanSpanningGrid extends PortletBeanGrid {
23
24     /**
25      * This following portletTable reference table is the heart of this
26      * spanning grid layout manager. It's format is the following :
27      *
28      * ¦ Column 1 ¦ Column 2 ¦ Column 3 ¦
29      * ------+-------------+-------------+-------------+
30      * Row 1 ¦ Portlet 1 Portlet 1 ¦ Portlet 2 ¦
31      * ------+-------------+-------------+-------------+
32      * Row 2 ¦ Portlet 3 ¦ Portlet 4 Portlet 4 ¦
33      * ------+ + + +
34      * Row 3 ¦ Portlet 3 ¦ Portlet 4 Portlet 4 ¦
35      * ------+-------------+-------------+-------------+
36      *
37      * Each entry of the grid is an Object, so in this case a PortletBean.
38      * So if a portlet occupies multiple rows and/or columns the reference
39      * to it's PortletBean object will be stored multiple times.
40      */

41     private Grid2D portletTable = new Grid2D();
42
43     /**
44      * Used to insert portlets in the grid, taking care of spanning information
45      * such as height and width. The table is first checked to make sure there
46      * is enough room for the portlet. If not, an exception is raised.
47      * @param portlet the portlet to add to the table.
48      */

49     private void addToTable(PortletBean portlet)
50     throws JahiaException {
51         int row = portlet.getPortletRow();
52         int col = portlet.getPortletColumn();
53         int height = portlet.getPortletH();
54         int width = portlet.getPortletW();
55         /*
56         JahiaConsole.println("PortletBeanSpanningGrid.addToTable", "Adding portlet to table " +
57                              "(" + Integer.toString(row) + "," + Integer.toString(col) + ") size=(" +
58                              Integer.toString(width) + "," + Integer.toString(height) + ")");
59         */

60         // let's do a sanity check on the coordinates first...
61
if ((row < 0) || (col < 0)) {
62             throw new JahiaException("PortletBeanSpanningGrid.addToTable",
63                                      "Portlet coordinates are invalid. (" + Integer.toString(row) + ", " + Integer.toString(col) + " )",
64                                      JahiaException.PAGE_ERROR,
65                                      JahiaException.ERROR_SEVERITY);
66         }
67
68         // now let's check the space is free...
69
boolean isFree = true;
70         for (int i = 0; i < height; i++) {
71             for (int j = 0; j < width; j++) {
72                 try {
73                     PortletBean curPortlet = (PortletBean) portletTable.getElementAt(row + i, col + j);
74                     if (curPortlet != null) {
75                         isFree = false;
76                     }
77                 } catch (ArrayIndexOutOfBoundsException JavaDoc aioobe) {
78                 }
79             }
80         }
81         if (!isFree) {
82             throw new JahiaException("PortletBeanSpanningGrid.addToTable",
83                                      "A portlet is already occupying that position",
84                                      JahiaException.PAGE_ERROR,
85                                      JahiaException.ERROR_SEVERITY);
86         }
87         // we now know this position is completely free, let's add it to the
88
// table...
89
for (int i = 0; i < height; i++) {
90             for (int j = 0; j < width; j++) {
91                 portletTable.setElementAt(row+i, col+j, portlet);
92             }
93         }
94     }
95
96     /**
97      * Rebuilds the internal grid table. This iterates through the lists
98      * portlets to build the internal representation.
99      */

100     private void rebuildGridTable() throws JahiaException {
101         JahiaConsole.println("PortletBeanSpanningGrid.rebuildGridTable",
102                              "Rebuilding reference table for " +
103                              Integer.toString(this.size()) + " portlets...");
104         // let's now recreate the grid of positions
105
portletTable.clear();
106         for (int i=0; i < this.size(); i++) {
107             PortletBean portlet = (PortletBean) this.elementAt(i);
108             if (portlet != null) {
109                 this.addToTable(portlet);
110             }
111         }
112         this.debugDisplayGrid();
113     }
114
115     public PortletBeanSpanningGrid() {
116     }
117
118     /**
119      * Copy constructor
120      * @param sourceSet original set to copy from
121      */

122     public PortletBeanSpanningGrid(PortletBeanSet sourceSet)
123     throws JahiaException {
124         Enumeration JavaDoc sourceElements = sourceSet.elements();
125         while (sourceElements.hasMoreElements()) {
126             PortletBean portlet = (PortletBean) sourceElements.nextElement();
127             this.add(portlet);
128         }
129     }
130
131     /**
132      * This method is intended to reset all the portlets to a height and width
133      * of 1 and organize their position in the number of columns passed as a
134      * parameter. The first portlet will at coordinates (row, column) (0, 1),
135      * the second at (0, 2) until the column length is reached, and then it
136      * continues on the second row...
137      * @param nbColums width in columns of new portlet arrangement...
138      * @throws JahiaException in case of problems rebuilding the internal
139      * portlet reference table.
140      */

141     public void resetPortlets(int nbColumns) throws JahiaException {
142         Enumeration JavaDoc sourceElements = this.elements();
143         int row = 0;
144         int column = 0;
145         while (sourceElements.hasMoreElements()) {
146             PortletBean portlet = (PortletBean) sourceElements.nextElement();
147             portlet.setPortletH(1);
148             portlet.setPortletW(1);
149             portlet.setPortletRow(row);
150             portlet.setPortletColumn(column);
151             column++;
152             if (column == nbColumns) {
153                 column = 0;
154                 row++;
155             }
156         }
157         rebuildGridTable();
158     }
159
160     /**
161      * Insert a new portlet into the set. This is simply an extension of the
162      * parent class' method, in order to add spanning class table information.
163      *
164      * WARNING : this method modifies the position of the portlet bean object !!
165      * @param portlet PortletBean object to insert in the grid. This object will
166      * also be modified so that the correct position is reflected in the portlet
167      * @returns true on success, false on failure (failure is not defined for the
168      * moment)
169      */

170     public boolean add(PortletBean portlet) {
171         // we set the default values of height and width to 1 because this is
172
// what is used by default on this system.
173
if ((portlet.getPortletH() == 0) || (portlet.getPortletW() == 0)) {
174             portlet.setPortletH(1);
175             portlet.setPortletW(1);
176         }
177         // let's do a sanity check on the coordinates.
178
if ((portlet.getPortletRow() < 0) || (portlet.getPortletColumn() < 0)) {
179             // fixme : should we correct the coordinates or not ?
180
int maxRow = getRowCount();
181             int oldRow = portlet.getPortletRow();
182             int oldCol = portlet.getPortletColumn();
183             portlet.setPortletRow(maxRow);
184             portlet.setPortletColumn(0);
185             JahiaConsole.println("PortletBeanSpanningGrid.add", "Correcting invalid coordinates (" +
186                                                                 oldRow + ", " + oldCol + ") to (" +
187                                                                 portlet.getPortletRow() + ", " + portlet.getPortletColumn() + ")");
188
189         }
190
191
192         // let's check if the position is already busy or not checking.
193
PortletBean testPortlet = null;
194         try {
195             testPortlet = (PortletBean) portletTable.getElementAt(portlet.getPortletRow(), portlet.getPortletColumn());
196         } catch (ArrayIndexOutOfBoundsException JavaDoc aioobe) {
197             // do nothing...this probably means that the table isn't busy at this position or that it's empty...
198
}
199
200         if (testPortlet != null) {
201             // we have found a conflict, let's resolve it.
202
int maxRow = getRowCount();
203             portlet.setPortletRow(maxRow);
204             portlet.setPortletColumn(0);
205             JahiaConsole.println("PortletBeanSpanningGrid.add", "Conflict found, modifying new portlet position to row=" + maxRow + " column=0");
206         }
207
208         boolean parentResult = super.add(portlet);
209         try {
210             addToTable(portlet);
211         } catch (JahiaException je) {
212             return false;
213         }
214         return parentResult;
215     }
216
217     /**
218      * Retrieve a portlet bean for the internal reference table. Given a
219      * position, this function retrieves the portlet that occupies that location,
220      * wether it's the beginning position or anywhere within the location
221      * (rectangular) it occupies. This function is targeted toward rendering
222      * functions, such as JSP tables that would need to use this.
223      *
224      * A good way to use this method is for example to retrieve the portlet
225      * with a set of coordinates, and then compare the portlets beginning row
226      * and column with the coordinates specified to this method. If they are
227      * equals we are at the beginning coordinates of a portlet, otherwise
228      * we are inside a portlet.
229      *
230      * @param row the row at which to retrieve the portlet from
231      * @param column the column at which to retrieve the portlet from
232      *
233      * @returns a portletbean occupying the specified position or null it none
234      * was found
235      */

236     public PortletBean getPortletFromRefTable(int row, int column) {
237         PortletBean portlet = (PortletBean) this.portletTable.getElementAt(row, column);
238         return portlet;
239     }
240
241     /**
242      * Retrieves the column count present in the grid. This is obtained by going
243      * through all the portlets and keeping the maximal value.
244      * Note : this might mean that some columns do not contain portlets.
245      * @returns an integer that represents the maximal column value in the grid
246      * @todo investigate how this behaves when column "holes" are present
247      */

248     public int getColumnCount() {
249         columnCount = 0;
250         Enumeration JavaDoc portletBeanEnum = this.elements();
251         while (portletBeanEnum.hasMoreElements()) {
252             PortletBean portlet = (PortletBean) portletBeanEnum.nextElement();
253             if (portlet.getPortletColumn() + portlet.getPortletW() > columnCount) {
254                 columnCount = portlet.getPortletColumn() + portlet.getPortletW();
255             }
256         }
257         return columnCount;
258     }
259
260     /**
261      * Retrieves the column count in the specified row.
262      * @param rowID the identifier (0-based) of the row in which we want to count
263      * the columns.
264      * @returns an integer representing the number of columns in the specified
265      * row
266      */

267     public int getColumnCount (int rowID) throws JahiaException {
268         rebuildGridTable();
269         int resultColumnCount = 0;
270         if ((rowID < 0) || (rowID >= getRowCount())) {
271             // invalid column number, let's just return 0
272
/** @todo we might want to change this behavior to return another
273              * value or an exception
274              */

275             return 0;
276         }
277         for (int i = 0; i < portletTable.getColumnCount(); i++) {
278             PortletBean curPortlet = (PortletBean) portletTable.getElementAt(rowID, i);
279             if (curPortlet != null) {
280                 if (i+1 > resultColumnCount) {
281                     resultColumnCount = i+1;
282                 }
283             }
284         }
285         return resultColumnCount;
286     }
287
288     /**
289      * Retrieves the row count present in the grid. This is obtained by going
290      * through all the portlets and keeping the maximal value.
291      * Note : this might mean that some rows do not contain portlets.
292      * @returns an integer that represents the maximal row value in the grid
293      * @todo investigate how this behaves when row "holes" are present in the
294      * grid
295      */

296     public int getRowCount() {
297         rowCount = 0;
298         Enumeration JavaDoc portletBeanEnum = this.elements();
299         while (portletBeanEnum.hasMoreElements()) {
300             PortletBean portlet = (PortletBean) portletBeanEnum.nextElement();
301             if (portlet.getPortletRow() + portlet.getPortletH() > rowCount) {
302                 rowCount = portlet.getPortletRow() + portlet.getPortletH();
303             }
304         }
305         return rowCount;
306     }
307
308     /**
309      * Retrieves the row count present in the grid at the specified column.
310      * @param columnID the identifier (0-based) of the column we want to get the
311      * row count of.
312      * @returns an integer that represents the maximal row value in the specified
313      * column
314      */

315     public int getRowCount(int columnID) throws JahiaException {
316         return this.getRowCountWithoutPortlet(columnID, -1);
317     }
318
319     /**
320      * Retrieves the row count present in the grid at the specified column.
321      * @param columnID the identifier (0-based) of the column we want to get the
322      * row count of.
323      * @param portletIDToIgnore an identifier of a portlet to ignore in the row
324      * count. This is useful when we want to get the row count WITHOUT a specific
325      * portlet (used for moves).
326      * @returns an integer that represents the maximal row value in the specified
327      * column
328      */

329     public int getRowCountWithoutPortlet(int columnID, int portletIDToIgnore)
330     throws JahiaException {
331         rebuildGridTable();
332         int resultRowCount = 0;
333         if ((columnID < 0) || (columnID >= getColumnCount())) {
334             // invalid column number, let's just return 0
335
/** @todo we might want to change this behavior to return another
336              * value or an exception
337              */

338             return 0;
339         }
340         for (int i = 0; i < portletTable.getRowCount(); i++) {
341             PortletBean curPortlet = (PortletBean) portletTable.getElementAt(i, columnID);
342             if (curPortlet != null) {
343                 if ( (curPortlet.getPortletID() != portletIDToIgnore) ||
344                      (portletIDToIgnore == -1) ) {
345                     if ( (i+1) > resultRowCount ) {
346                         resultRowCount = i+1;
347                     }
348                 }
349             }
350         }
351         return resultRowCount;
352     }
353
354     /**
355      * This vector is used to store the start rows at which the columns should
356      * be moved. This is not very elegant since this structure shouldn't be
357      * "global" to this class, but this avoids a nested class so it shouldn't
358      * be too problematic...
359      *
360      * Each entry represents a column.
361      * @associates MarkEntry
362      */

363     private Vector JavaDoc markedColumnList = null;
364
365     /**
366      * Small debug function that displays a vector of MarkEntry objects onto
367      * the Jahia console.
368      * @param message A message to display before each line of the output,
369      * typically used to give the name of the variable, which is useful for
370      * debugging purposes.
371      * @param markedList a Vector containing only MarkEntry objects, to be
372      * displayed on the console.
373      */

374     private void debugDisplayMarkedList(String JavaDoc message, Vector JavaDoc markedList) {
375         if (markedList == null) {
376             JahiaConsole.println("PortletBeanSpanningGrid.debugDisplayMarkedList",
377                                  message + " markedList is null");
378             return;
379         }
380
381         for (int i=0; i < markedList.size(); i++) {
382             MarkEntry curEntry = (MarkEntry) markedList.elementAt(i);
383             JahiaConsole.println("PortletBeanSpanningGrid.debugDisplayMarkedList",
384                                  message + "[" + i + "]" +
385                                  " mark start=" + curEntry.getMarkStart() +
386                                  " processed=" + curEntry.getProcessedState());
387         }
388     }
389
390
391     /**
392      * This method marks columns in order to prepare for a move down. We need to
393      * do this because we may have objects that cross column boundaries
394      * @param column starting column from which we want to start moving stuff
395      * @param startingRow starting row from which to start looking at portlets
396      * to mark down for move
397      */

398     private void findHorizontalEdgeForMoving(int column, int startingRow)
399     throws JahiaException {
400         JahiaConsole.println("PortletBeanSpanningGrid.findHorizontalEdgeForMoving",
401                              "Building horizontal edge");
402         if (markedColumnList == null) {
403             markedColumnList = new Vector JavaDoc();
404             // set all moves to deactivated, indicated by the -1 value
405
for (int i = 0; i < this.getColumnCount(); i++) {
406                 markedColumnList.add(new MarkEntry());
407             }
408         }
409
410         if ( (column >= this.getColumnCount()) || (column < 0) ) {
411             return;
412         }
413
414         MarkEntry thisColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(column);
415         if (thisColumnMarkEntry == null) {
416             // how can this happen we just initialized it ?
417
throw new JahiaException("PortletBeanSpanningGrid.findHorizontalEdgeForMoving",
418                                      "Invalid markedColumnList, probably a problem during initialization...",
419                                      JahiaException.TEMPLATE_ERROR,
420                                      JahiaException.ERROR_SEVERITY);
421         }
422         // let's set the initial column's starting row...
423
// and check if there is a portlet at that position, otherwise we
424
// iterate through the rows to find the first portlet
425
int markerStart = -1;
426         for (int i=startingRow; i < getRowCount(column); i++) {
427             PortletBean portlet = (PortletBean) this.portletTable.getElementAt(i, column);
428             if (portlet != null) {
429                 markerStart = i;
430                 break;
431             }
432         }
433         if (markerStart == -1) {
434             return;
435         }
436         thisColumnMarkEntry.setMarkStart(markerStart);
437         /**
438          * Basically what we want to do now is go down the initial column, and
439          * everytime we meet a portlet that covers multiple columns, we iterate
440          * over that column to mark other columns and so on...
441          */

442         recursiveHorizontalEdgeMarking(column, startingRow);
443     }
444
445     /**
446      * This is a recursive method used by the findHorizontalEdgeForMoving method.
447      * It assumes that the markedColumnList has been initialized to the size
448      * of the current column list. Failure to do so will raise an exception.
449      * @param column the column at which to start recursive column marking
450      * @param startingRow the row in the column at which to start recursive
451      * column marking
452      * @returns number of columns set in this iteration of the call
453      * @exception JahiaException thrown if the markedColumnList variable is not
454      * propertly initialized.
455      */

456     private int recursiveHorizontalEdgeMarking(int column, int startingRow)
457     throws JahiaException {
458         int numberOfNewMarks = 0;
459         MarkEntry thisColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(column);
460         if (thisColumnMarkEntry == null) {
461             throw new JahiaException("PortletBeanSpanningGrid.recursiveHorizontalEdgeMarking",
462                                      "Invalid markedColumnList, probably a problem during initialization...",
463                                      JahiaException.TEMPLATE_ERROR,
464                                      JahiaException.ERROR_SEVERITY);
465         }
466         if (thisColumnMarkEntry.getProcessedState() == true) {
467             // column already processed, let's exit immediately.
468
return numberOfNewMarks;
469         }
470         for (int i=startingRow; i < this.getRowCount(column); i++) {
471             PortletBean portlet = (PortletBean) this.portletTable.getElementAt(i, column);
472             if (portlet != null) {
473                 if ( (portlet.getPortletW() > 1) ) {
474                     /**
475                      * multiple possibilities now, either :
476                      * 1. the portlet starts here
477                      * 2. the portlet spans through here
478                      * 3. the portlet ends here.
479                      * first let's test is the portlet's position is the current
480                      * cell
481                      */

482                      for (int j=portlet.getPortletColumn(); j < portlet.getPortletColumn() + portlet.getPortletW(); j++) {
483                         // let's iterate through the columns, marking those that
484
// still need marking...
485
MarkEntry curColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(j);
486                         if (curColumnMarkEntry == null) {
487                             /**
488                              * serious problem here, this should happen since
489                              * we normally initialize the column list. This
490                              * probably means somebody is trying to call this
491                              * method directly without going through
492                              * findHorizontalEdgeForMoving
493                              */

494                              throw new JahiaException("PortletBeanSpanningGrid.recursiveHorizontalEdgeMarking",
495                                                       "Invalid markedColumnList, probably a problem during initialization...",
496                                                       JahiaException.TEMPLATE_ERROR,
497                                                       JahiaException.ERROR_SEVERITY);
498                         }
499                         if ((curColumnMarkEntry.getMarkStart() == -1) ||
500                             (curColumnMarkEntry.getMarkStart() > i) ) {
501                             // this column has not yet been marked or the value
502
// of the current mark is lower (ie higher in value)
503
// then we mark this column.
504
curColumnMarkEntry.setMarkStart(i);
505                             numberOfNewMarks++;
506                         }
507                      }
508                      if ( (portlet.getPortletRow() == i) &&
509                           (portlet.getPortletColumn() == column) ) {
510                         // the portlet indeed starts here...
511
} else {
512                         // the portlet started on another column...
513
}
514                 } else {
515                     /**
516                      * portlet is single cell size, nothing to do, except maybe
517                      * checking if the size is zero, but this shouldn't be the
518                      * case :)
519                      */

520                 }
521             } else {
522             }
523         }
524         // now let's mark this column as being processed, so that we never
525
// process it twice...
526
MarkEntry curColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(column);
527         if (curColumnMarkEntry != null) {
528             curColumnMarkEntry.setProcessedState(true);
529         } else {
530             /**
531              * serious problem here, this should happen since we normally
532              * initialize the column list. This probably means somebody is
533              * trying to call this method directly without going through
534              * findHorizontalEdgeForMoving
535              */

536             throw new JahiaException("PortletBeanSpanningGrid.recursiveHorizontalEdgeMarking",
537                                      "Invalid markedColumnList, probably a problem during initialization...",
538                                      JahiaException.TEMPLATE_ERROR,
539                                      JahiaException.ERROR_SEVERITY);
540         }
541         // recursive descent to the left column
542
if ( (column-1) >= 0) {
543             MarkEntry previousColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(column-1);
544             if ( (previousColumnMarkEntry.getProcessedState() == false) &&
545                  (previousColumnMarkEntry.getMarkStart() != -1 ) ) {
546                 recursiveHorizontalEdgeMarking(column-1, previousColumnMarkEntry.getMarkStart());
547             }
548         }
549         // recursive descent to the right column
550
if ( (column + 1) < this.getColumnCount() ) {
551             MarkEntry nextColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(column+1);
552             if ( (nextColumnMarkEntry.getProcessedState() == false) &&
553                  (nextColumnMarkEntry.getMarkStart() != -1 ) ) {
554                 recursiveHorizontalEdgeMarking(column+1, nextColumnMarkEntry.getMarkStart());
555             }
556         }
557         return numberOfNewMarks;
558     }
559
560     /**
561      * Moves the columns marked in the markedColumnList table down.
562      * Warning : this must be done only after successfull completion of the
563      * the findHorizontalEdgeForMoving method.
564      * @param increment an integer specifying the number of rows to move all
565      * the columns down.
566      */

567     private void moveColumnsDown(int increment)
568     throws JahiaException {
569         for (int i=0; i < this.getColumnCount(); i++) {
570             MarkEntry curColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(i);
571             if (curColumnMarkEntry == null) {
572                 throw new JahiaException("PortletBeanSpanningGrid.moveColumnsDown",
573                                          "Invalid markedColumnList, probably a problem during initialization...",
574                                          JahiaException.TEMPLATE_ERROR,
575                                          JahiaException.ERROR_SEVERITY);
576             }
577             if (curColumnMarkEntry.getMarkStart() != -1) {
578                 // column is activated for move, let's move it, starting at the
579
// bottom upwards...
580
for (int j = this.getRowCount(i)-1; j >= curColumnMarkEntry.getMarkStart(); j--) {
581                     PortletBean portlet = (PortletBean) this.getPosPortlet(j, i);
582                     if (portlet != null) {
583                         portlet.setPortletRow(portlet.getPortletRow()+increment);
584                     }
585                 }
586             }
587         }
588
589         rebuildGridTable();
590         markedColumnList = null;
591     }
592
593     /**
594      * Moves the columns marked in the markedColumnList table up. An algorithm
595      * is used to determine if the blocks have enough space to move up or not.
596      * Warning : this must be done only after successfull completion of the
597      * the findHorizontalEdgeForMoving method.
598      *
599      * @param increment an integer specifying the number of rows to move all
600      * the columns down.
601      * @param startingColumn column at which to start moving portlets up in a
602      * pyramidal model (starting at the top of the pyramid)
603      */

604     private void moveColumnsUp(int increment, int startingColumn)
605     throws JahiaException {
606         /**
607          * The basic idea here is to go row by row instead of column by column,
608          * so as to make sure that we don't miss an opportunity to use "holes"
609          * in the grid to move objects up...
610          */

611
612         if ((startingColumn < 0) || (startingColumn >= this.getColumnCount())) {
613             return;
614         }
615
616         MarkEntry startColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(startingColumn);
617         if (startColumnMarkEntry == null) {
618             throw new JahiaException("PortletBeanSpanningGrid.moveColumnsUp",
619                                      "Invalid markedColumnList, probably a problem during initialization...",
620                                      JahiaException.TEMPLATE_ERROR,
621                                      JahiaException.ERROR_SEVERITY);
622         }
623         int startingRow = startColumnMarkEntry.getMarkStart();
624
625         if (startingRow == -1) {
626             // column is not marked for some reason, let's quit immediately...
627
return;
628         }
629
630         for (int i = startingRow; i < this.getRowCount(); i++) {
631             // for each row we move first left, then right, starting at the
632
// starting column on each row...
633

634             if (startingColumn > 0) {
635                 for (int j = startingColumn-1; j >= 0; j--) {
636                     MarkEntry curColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(j);
637                     if (curColumnMarkEntry == null) {
638                         throw new JahiaException("PortletBeanSpanningGrid.moveColumnsUp",
639                                                  "Invalid markedColumnList, probably a problem during initialization...",
640                                                  JahiaException.TEMPLATE_ERROR,
641                                                  JahiaException.ERROR_SEVERITY);
642                     }
643                     if (curColumnMarkEntry.getMarkStart() != -1) {
644                         PortletBean portlet = (PortletBean) this.getPosPortlet(i, j);
645                         if (portlet != null) {
646                             // now let's check if there is enough space to move this
647
// portlet up...
648
boolean hasSpace = true;
649                             for (int k=0; k < increment; k++) {
650                                 for (int l=0; l < portlet.getPortletW(); l++) {
651                                     PortletBean posPortlet = (PortletBean) this.getPosPortlet(portlet.getPortletRow() - increment+k, portlet.getPortletColumn() + l);
652                                     if (posPortlet != null) {
653                                         hasSpace = false;
654                                     }
655                                 }
656                             }
657                             if (hasSpace) {
658                                 portlet.setPortletRow(portlet.getPortletRow()-increment);
659                             }
660                         }
661                     }
662                 }
663             }
664
665             for (int j = startingColumn; j < this.getColumnCount(); j++) {
666                 MarkEntry curColumnMarkEntry = (MarkEntry) markedColumnList.elementAt(j);
667                 if (curColumnMarkEntry == null) {
668                     throw new JahiaException("PortletBeanSpanningGrid.moveColumnsUp",
669                                              "Invalid markedColumnList, probably a problem during initialization...",
670                                              JahiaException.TEMPLATE_ERROR,
671                                              JahiaException.ERROR_SEVERITY);
672                 }
673                 if (curColumnMarkEntry.getMarkStart() != -1) {
674                     PortletBean portlet = (PortletBean) this.getPosPortlet(i, j);
675                     if (portlet != null) {
676                         // now let's check if there is enough space to move this
677
// portlet up...
678
boolean hasSpace = true;
679                         for (int k=0; k < increment; k++) {
680                             for (int l=0; l < portlet.getPortletW(); l++) {
681                                 PortletBean posPortlet = (PortletBean) this.getPosPortlet(portlet.getPortletRow() - increment+k, portlet.getPortletColumn() + l);
682                                 if (posPortlet != null) {
683                                     hasSpace = false;
684                                 }
685                             }
686                         }
687                         if (hasSpace) {
688                             portlet.setPortletRow(portlet.getPortletRow()-increment);
689                         }
690                     }
691                 }
692             }
693         }
694
695         rebuildGridTable();
696         markedColumnList = null;
697     }
698
699     /**
700      * @todo VERY UGLY cut&paste below, see if we can get rid of this by doing
701      * a single horizontal & vertical processing system...
702      */

703
704     /**
705      * This vector is used to store the start columns at which the columns should
706      * be moved. This is not very elegant since this structure shouldn't be
707      * "global" to this class, but this avoids a nested class so it shouldn't
708      * be too problematic...
709      *
710      * Each entry represents a row.
711      * @associates MarkEntry
712      */

713     private Vector JavaDoc markedRowList = null;
714
715     /**
716      * This method marks rows in order to prepare for a move right. We need to
717      * do this because we may have objects that cross row boundaries
718      * @param row starting row from which we want to start moving stuff
719      * @param startingColumn starting column from which to start looking at portlets
720      * to mark down for move
721      */

722     private void findVerticalEdgeForMoving(int row, int startingColumn)
723     throws JahiaException {
724
725         if (markedRowList == null) {
726             markedRowList = new Vector JavaDoc();
727             // set all moves to deactivated, indicated by the -1 value
728
for (int i = 0; i < this.getRowCount(); i++) {
729                 markedRowList.add(new MarkEntry());
730             }
731         }
732
733         if ( (row >= this.getRowCount()) || (row < 0) ) {
734             return;
735         }
736
737         MarkEntry thisRowMarkEntry = (MarkEntry) markedRowList.elementAt(row);
738         if (thisRowMarkEntry == null) {
739             // how can this happen we just initialized it ?
740
throw new JahiaException("PortletBeanSpanningGrid.findVerticalEdgeForMoving",
741                                      "Invalid markedRowList, probably a problem during initialization...",
742                                      JahiaException.TEMPLATE_ERROR,
743                                      JahiaException.ERROR_SEVERITY);
744         }
745         // let's set the initial row's starting column...
746
// and check if there is a portlet at that position, otherwise we
747
// iterate through the columns to find the first portlet
748
int markerStart = -1;
749         for (int i=startingColumn; i < getColumnCount(row); i++) {
750             PortletBean portlet = (PortletBean) this.portletTable.getElementAt(row, i);
751             if (portlet != null) {
752                 markerStart = i;
753                 break;
754             }
755         }
756         if (markerStart == -1) {
757             return;
758         }
759         thisRowMarkEntry.setMarkStart(markerStart);
760         /**
761          * Basically what we want to do now is go down the initial row, and
762          * everytime we meet a portlet that covers multiple rows, we iterate
763          * over that row to mark other rows and so on...
764          */

765         recursiveVerticalEdgeMarking(row, startingColumn);
766     }
767
768     /**
769      * This is a recursive method used by the findVerticalEdgeForMoving method.
770      * It assumes that the markedRowList has been initialized to the size
771      * of the current row list. Failure to do so will raise an exception.
772      * @param row the row at which to start recursive row marking
773      * @param startingColumn the column in the row at which to start recursive
774      * row marking
775      * @returns number of rows set in this iteration of the call
776      * @exception JahiaException thrown if the markedColumnList variable is not
777      * propertly initialized.
778      */

779     private int recursiveVerticalEdgeMarking(int row, int startingColumn)
780     throws JahiaException {
781         int numberOfNewMarks = 0;
782         MarkEntry thisRowMarkEntry = (MarkEntry) markedRowList.elementAt(row);
783         if (thisRowMarkEntry == null) {
784             throw new JahiaException("PortletBeanSpanningGrid.recursiveVerticalEdgeMarking",
785                                      "Invalid markedRowList, probably a problem during initialization...",
786                                      JahiaException.TEMPLATE_ERROR,
787                                      JahiaException.ERROR_SEVERITY);
788         }
789         if (thisRowMarkEntry.getProcessedState() == true) {
790             // column already processed, let's exit immediately.
791
return numberOfNewMarks;
792         }
793         for (int i=startingColumn; i < this.getColumnCount(row); i++) {
794             PortletBean portlet = (PortletBean) this.portletTable.getElementAt(row, i);
795             if (portlet != null) {
796                 if ( (portlet.getPortletH() > 1) ) {
797                     /**
798                      * multiple possibilities now, either :
799                      * 1. the portlet starts here
800                      * 2. the portlet spans through here
801                      * 3. the portlet ends here.
802                      * first let's test is the portlet's position is the current
803                      * cell
804                      */

805                      for (int j=portlet.getPortletRow(); j < portlet.getPortletRow() + portlet.getPortletH(); j++) {
806                         // let's iterate through the columns, marking those that
807
// still need marking...
808
MarkEntry curRowMarkEntry = (MarkEntry) markedRowList.elementAt(j);
809                         if (curRowMarkEntry == null) {
810                             /**
811                              * serious problem here, this should happen since
812                              * we normally initialize the column list. This
813                              * probably means somebody is trying to call this
814                              * method directly without going through
815                              * findHorizontalEdgeForMoving
816                              */

817                              throw new JahiaException("PortletBeanSpanningGrid.recursiveVerticalEdgeMarking",
818                                                       "Invalid markedRowList, probably a problem during initialization...",
819                                                       JahiaException.TEMPLATE_ERROR,
820                                                       JahiaException.ERROR_SEVERITY);
821                         }
822                         if ((curRowMarkEntry.getMarkStart() == -1) ||
823                             (curRowMarkEntry.getMarkStart() > i) ) {
824                             // this column has not yet been marked or the value
825
// of the current mark is lower (ie higher in value)
826
// then we mark this column.
827
curRowMarkEntry.setMarkStart(i);
828                             numberOfNewMarks++;
829                         }
830                      }
831                      if ( (portlet.getPortletRow() == row) &&
832                           (portlet.getPortletColumn() == i) ) {
833                         // the portlet indeed starts here...
834
} else {
835                         // the portlet started on another column...
836
}
837                 } else {
838                     /**
839                      * portlet is single cell size, nothing to do, except maybe
840                      * checking if the size is zero, but this shouldn't be the
841                      * case :)
842                      */

843                 }
844             } else {
845             }
846         }
847         // now let's mark this column as being processed, so that we never
848
// process it twice...
849
MarkEntry curRowMarkEntry = (MarkEntry) markedRowList.elementAt(row);
850         if (curRowMarkEntry != null) {
851             curRowMarkEntry.setProcessedState(true);
852         } else {
853             /**
854              * serious problem here, this should happen since we normally
855              * initialize the column list. This probably means somebody is
856              * trying to call this method directly without going through
857              * findHorizontalEdgeForMoving
858              */

859             throw new JahiaException("PortletBeanSpanningGrid.recursiveVerticalEdgeMarking",
860                                      "Invalid markedRowList, probably a problem during initialization...",
861                                      JahiaException.TEMPLATE_ERROR,
862                                      JahiaException.ERROR_SEVERITY);
863         }
864         if ( (row-1) >= 0) {
865             MarkEntry previousRowMarkEntry = (MarkEntry) markedRowList.elementAt(row-1);
866             if ( (previousRowMarkEntry.getProcessedState() == false) &&
867                  (previousRowMarkEntry.getMarkStart() != -1 ) ) {
868                 recursiveVerticalEdgeMarking(row-1, previousRowMarkEntry.getMarkStart());
869             }
870         }
871         if ( (row + 1) < this.getRowCount() ) {
872             MarkEntry nextRowMarkEntry = (MarkEntry) markedRowList.elementAt(row+1);
873             if ( (nextRowMarkEntry.getProcessedState() == false) &&
874                  (nextRowMarkEntry.getMarkStart() != -1 ) ) {
875                 recursiveVerticalEdgeMarking(row+1, nextRowMarkEntry.getMarkStart());
876             }
877         }
878         return numberOfNewMarks;
879     }
880
881     /**
882      * Moves the rows marked in the markedRowList table to the right
883      * Warning : this must be done only after successfull completion of the
884      * the findVerticalEdge method.
885      * @param increment an integer specifying the number of columns to move all
886      * the rows to the right.
887      */

888     private void moveRowsRight(int increment)
889     throws JahiaException {
890         for (int i=0; i < this.getRowCount(); i++) {
891             MarkEntry curRowMarkEntry = (MarkEntry) markedRowList.elementAt(i);
892             if (curRowMarkEntry == null) {
893                 throw new JahiaException("PortletBeanSpanningGrid.moveRowsRight",
894                                          "Invalid markedRowList, probably a problem during initialization...",
895                                          JahiaException.TEMPLATE_ERROR,
896                                          JahiaException.ERROR_SEVERITY);
897             }
898             if (curRowMarkEntry.getMarkStart() != -1) {
899                 // column is activated for move, let's move it, starting at the
900
// bottom upwards...
901
for (int j = this.getColumnCount(i)-1; j >= curRowMarkEntry.getMarkStart(); j--) {
902                     PortletBean portlet = (PortletBean) this.getPosPortlet(i, j);
903                     if (portlet != null) {
904                         portlet.setPortletColumn(portlet.getPortletColumn()+increment);
905                     }
906                 }
907             }
908         }
909
910         rebuildGridTable();
911         markedRowList = null;
912     }
913
914     /**
915      * Moves the columns marked in the markedColumnList table up. An algorithm
916      * is used to determine if the blocks have enough space to move up or not.
917      * Warning : this must be done only after successfull completion of the
918      * the findVerticalEdgeForMoving method.
919      * @param increment an integer specifying the number of rows to move all
920      * the columns down.
921      * @param startingRow row at which to start moving portlets to the
922      * left in a pyramidal model (starting at the top of the pyramid going
923      * towards the right)
924      */

925     private void moveRowsLeft(int increment, int startingRow)
926     throws JahiaException {
927         /**
928          * The basic idea here is to go row by row instead of column by column,
929          * so as to make sure that we don't miss an opportunity to use "holes"
930          * in the grid to move objects up...
931          */

932
933         if ((startingRow < 0) || (startingRow >= getRowCount())) {
934             return;
935         }
936
937         MarkEntry startRowMarkEntry = (MarkEntry) markedRowList.elementAt(startingRow);
938         if (startRowMarkEntry == null) {
939             throw new JahiaException("PortletBeanSpanningGrid.moveColumnsUp",
940                                      "Invalid markedColumnList, probably a problem during initialization...",
941                                      JahiaException.TEMPLATE_ERROR,
942                                      JahiaException.ERROR_SEVERITY);
943         }
944         int startingColumn = startRowMarkEntry.getMarkStart();
945
946         if (startingColumn == -1) {
947             // row is not marked for some reason, let's quit immediately...
948
return;
949         }
950
951         for (int i = startingColumn; i < this.getColumnCount(); i++) {
952             // for each column we move first up, then down, starting at the
953
// starting row on each column...
954

955             if (startingRow > 0) {
956                 for (int j = startingRow-1; j >= 0; j--) {
957                     MarkEntry curRowMarkEntry = (MarkEntry) markedRowList.elementAt(j);
958                     if (curRowMarkEntry == null) {
959                         throw new JahiaException("PortletBeanSpanningGrid.moveRowsLeft",
960                                                  "Invalid markedRowList, probably a problem during initialization...",
961                                                  JahiaException.TEMPLATE_ERROR,
962                                                  JahiaException.ERROR_SEVERITY);
963                     }
964                     if (curRowMarkEntry.getMarkStart() != -1) {
965                         PortletBean portlet = (PortletBean) this.getPosPortlet(j, i);
966                         if (portlet != null) {
967                             // now let's check if there is enough space to move this
968
// portlet to the left...
969
boolean hasSpace = true;
970                             for (int k=0; k < increment; k++) {
971                                 for (int l=0; l < portlet.getPortletH(); l++) {
972                                     PortletBean posPortlet = (PortletBean) this.getPosPortlet(portlet.getPortletRow() + l, portlet.getPortletColumn() - increment+k);
973                                     if (posPortlet != null) {
974                                         hasSpace = false;
975                                     }
976                                 }
977                             }
978                             if (hasSpace) {
979                                 portlet.setPortletColumn(portlet.getPortletColumn()-increment);
980                             }
981                         }
982                     }
983                 }
984             }
985
986             for (int j = startingRow; j < this.getRowCount(); j++) {
987                 MarkEntry curRowMarkEntry = (MarkEntry) markedRowList.elementAt(j);
988                 if (curRowMarkEntry == null) {
989                     throw new JahiaException("PortletBeanSpanningGrid.moveRowsLeft",
990                                              "Invalid markedRowList, probably a problem during initialization...",
991                                              JahiaException.TEMPLATE_ERROR,
992                                              JahiaException.ERROR_SEVERITY);
993                 }
994                 if (curRowMarkEntry.getMarkStart() != -1) {
995                     PortletBean portlet = (PortletBean) this.getPosPortlet(j, i);
996                     if (portlet != null) {
997                         // now let's check if there is enough space to move this
998
// portlet to the left...
999
boolean hasSpace = true;
1000                        for (int k=0; k < increment; k++) {
1001                            for (int l=0; l < portlet.getPortletH(); l++) {
1002                                PortletBean posPortlet =
1003                                    (PortletBean) this.getPortletFromRefTable(
1004                                                    portlet.getPortletRow() + l,
1005                                                    portlet.getPortletColumn() - increment+k);
1006                                if (posPortlet != null) {
1007                                    hasSpace = false;
1008                                }
1009                            }
1010                        }
1011                        if (hasSpace) {
1012                            portlet.setPortletColumn(portlet.getPortletColumn()-increment);
1013                        }
1014                    }
1015                }
1016            }
1017        }
1018
1019        rebuildGridTable();
1020        markedRowList = null;
1021    }
1022
1023    /**
1024     * Move the portlet up by one row in the grid. If the row is already the top
1025     * one no movement is down. Otherwise the movement is done by :
1026     * - if the portlets have the same width, we swap positions with the
1027     * portlet above the one we want to move.
1028     * - if there is free space, let's use it (sorta swapping with it)
1029     * - if there isn't any free space, we put the portlet at the end of
1030     * new destination row. A little weird but avoids moving stuff around
1031     * for nothing.
1032     * @param portletID the identifier of the portlet to move
1033     * @throws JahiaException if the portlet corresponding to the identifier
1034     * cannot be found.
1035     */

1036    public void movePortletUp(int portletID)
1037    throws JahiaException {
1038        PortletBean targetPortlet = findPortlet(portletID);
1039        int currentWidth = targetPortlet.getPortletW();
1040        int currentHeight = targetPortlet.getPortletH();
1041        int oldRow = targetPortlet.getPortletRow();
1042        int oldColumn = targetPortlet.getPortletColumn();
1043        if (targetPortlet.getPortletRow() == 0) {
1044            // already at the top, do nothing
1045
} else {
1046
1047            if (swapPortletUp(portletID)) {
1048                return;
1049            }
1050            // portlets are NOT the same size, or no porlet at destination,
1051
// we must proceed another way...
1052
// first let's check if there simply isn't an empty space
1053
// we can fit into...
1054
boolean enoughFreeSpace = true;
1055            for (int i=0; i < currentWidth; i++) {
1056                PortletBean tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() - 1,
1057                                                                                  targetPortlet.getPortletColumn()+i);
1058                if (tempPortlet != null) {
1059                    enoughFreeSpace = false;
1060                }
1061            }
1062            if (!enoughFreeSpace) {
1063                // we could do an insertion method, but EV thought it
1064
// would be better to place the portlet at the end of
1065
// the destination row... so we're doing this instead.
1066
// Depending on how the user accepts this we might have
1067
// to change this behavior later on...
1068

1069                // First we determine the column at which to move the portlet
1070
// since we may span accross multiple rows...
1071
int destRowColumnCount = 0;
1072                for (int i=0; i < currentHeight; i++) {
1073                    if (this.getColumnCount(targetPortlet.getPortletRow()-1+i) > destRowColumnCount) {
1074                        destRowColumnCount = this.getColumnCount(targetPortlet.getPortletRow()-1+i);
1075                    }
1076                }
1077                targetPortlet.setPortletRow(targetPortlet.getPortletRow()-1);
1078                targetPortlet.setPortletColumn(destRowColumnCount);
1079            } else {
1080                targetPortlet.setPortletRow(targetPortlet.getPortletRow()-1);
1081            }
1082            rebuildGridTable();
1083            // now that we've moved the portlet, let's try to make use
1084
// of the freed space...
1085
for (int i=0; i < currentWidth; i++) {
1086
1087                PortletBean tempPortlet = null;
1088                if (areCoordinatesValid(oldRow + currentHeight - 1, targetPortlet.getPortletColumn() + i) ) {
1089                    tempPortlet = (PortletBean) portletTable.getElementAt(oldRow + currentHeight -1 ,
1090                                                                          targetPortlet.getPortletColumn()+i);
1091                    if (tempPortlet == null) {
1092                        this.findHorizontalEdgeForMoving(targetPortlet.getPortletColumn()+i, oldRow + currentHeight -1);
1093                        this.moveColumnsUp(1, targetPortlet.getPortletColumn()+i);
1094                    }
1095                }
1096            }
1097            rebuildGridTable();
1098        }
1099    }
1100
1101    /**
1102     * Moves the portlet down one row, creating a new row if it doesn't exist
1103     * @param portletID identifier of the portlet to be moved
1104     * @throws JahiaException if the portlet cannot be found.
1105     */

1106    public void movePortletDown(int portletID)
1107    throws JahiaException {
1108        PortletBean targetPortlet = findPortlet(portletID);
1109        int currentWidth = targetPortlet.getPortletW();
1110        int currentHeight = targetPortlet.getPortletH();
1111        if (targetPortlet.getPortletRow() + targetPortlet.getPortletH() == this.getRowCount(targetPortlet.getPortletColumn())) {
1112            // already at the last row...
1113
rowCount++;
1114            portletTable.setEmptyElementAt(targetPortlet.getPortletRow()+1, targetPortlet.getPortletColumn());
1115        }
1116
1117        if (swapPortletDown(portletID)) {
1118            return;
1119        }
1120        // portlets are NOT the same size, or no porlet at destination,
1121
// we must proceed another way...
1122
// first let's check if there simply isn't an empty space
1123
// we can fit into...
1124
boolean enoughFreeSpace = true;
1125        for (int i=0; i < currentWidth; i++) {
1126            PortletBean tempPortlet = null;
1127            if (areCoordinatesValid(targetPortlet.getPortletRow() + targetPortlet.getPortletH(),
1128                                    targetPortlet.getPortletColumn()+i) ) {
1129                tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + targetPortlet.getPortletH(),
1130                                                                      targetPortlet.getPortletColumn()+i);
1131            }
1132            if (tempPortlet != null) {
1133                enoughFreeSpace = false;
1134            }
1135        }
1136        if (!enoughFreeSpace) {
1137            for (int i=0; i < currentWidth; i++) {
1138                PortletBean tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + 1,
1139                                                                                  targetPortlet.getPortletColumn()+i);
1140                if (tempPortlet != null) {
1141                    this.findHorizontalEdgeForMoving(targetPortlet.getPortletColumn()+i, targetPortlet.getPortletRow() + currentHeight);
1142                    this.moveColumnsDown(1);
1143                }
1144            }
1145            targetPortlet.setPortletRow(targetPortlet.getPortletRow()+1);
1146        } else {
1147            targetPortlet.setPortletRow(targetPortlet.getPortletRow()+1);
1148        }
1149        // now that we've moved the portlet, let's try to make use
1150
// of the freed space...
1151
rebuildGridTable();
1152    }
1153
1154    /**
1155     * Moves the specified portlet one column to the left. If the portlet is
1156     * already in the leftmost column, this method does nothing.
1157     * @param portletID identifier of the portlet to be moved
1158     * @throws JahiaException if the portlet corresponding to the identifier
1159     * cannot be found
1160     */

1161    public void movePortletLeft(int portletID)
1162    throws JahiaException {
1163        PortletBean targetPortlet = findPortlet(portletID);
1164        int oldRow = targetPortlet.getPortletRow();
1165        int oldColumn = targetPortlet.getPortletColumn();
1166        if (targetPortlet.getPortletColumn() == 0) {
1167            /** @todo for the moment we just do nothing, but we could also
1168             * decide to move everything down and insert a new first row with
1169             * our portlet alone on it
1170             */

1171        } else {
1172
1173            // first we must find insertion point in the left column...
1174

1175            int insertionRow = targetPortlet.getPortletRow();
1176            int insertionColumn = targetPortlet.getPortletColumn() - 1;
1177            /* Let's check if we are inserting in a column that is smaller than
1178               the current row position. If so reduce the row to include at the
1179               end of the column, avoiding "hole" creation.
1180             */

1181            if (targetPortlet.getPortletRow() >= getRowCountWithoutPortlet(targetPortlet.getPortletColumn() - 1, targetPortlet.getPortletID()) ) {
1182                insertionRow = getRowCountWithoutPortlet(targetPortlet.getPortletColumn() - 1, targetPortlet.getPortletID());
1183            } else {
1184                PortletBean testPortlet = (PortletBean) this.portletTable.getElementAt(targetPortlet.getPortletRow(),
1185                                                                                       targetPortlet.getPortletColumn()-1);
1186                if (testPortlet != null) {
1187                    if (testPortlet.getPortletRow() == targetPortlet.getPortletRow() ) {
1188                        // both portlets start on the same row, all we need to
1189
// know not is if the test portlet starts on the previous
1190
// column or not...
1191
if (testPortlet.getPortletColumn() != targetPortlet.getPortletColumn() - 1) {
1192                            // destination column is not where the test portlet
1193
// starts...
1194
insertionColumn = testPortlet.getPortletColumn();
1195                        }
1196                    } else {
1197                        // portlets don't start on the same row, let's insert
1198
// immediately below the test portlet.
1199
insertionRow = testPortlet.getPortletRow() + testPortlet.getPortletH();
1200                        // insertionColumn = testPortlet.getPortletColumn();
1201
}
1202                }
1203
1204            }
1205
1206            // now let's make room in the new column
1207
boolean enoughFreeSpace = true;
1208            for (int i=0; i < targetPortlet.getPortletH(); i++) {
1209                PortletBean tempPortlet = (PortletBean) portletTable.getElementAt(insertionRow + i,
1210                                                                                  targetPortlet.getPortletColumn()-1);
1211                if (tempPortlet != null) {
1212                    enoughFreeSpace = false;
1213                }
1214            }
1215            if (!enoughFreeSpace) {
1216                this.findHorizontalEdgeForMoving(insertionColumn, insertionRow);
1217                debugDisplayMarkedList("markedColumnList", markedColumnList);
1218                this.moveColumnsDown(targetPortlet.getPortletH());
1219            }
1220
1221            // let's set the new position
1222
targetPortlet.setPortletRow(insertionRow);
1223            targetPortlet.setPortletColumn(targetPortlet.getPortletColumn()-1);
1224
1225            rebuildGridTable();
1226
1227            // and let's reclaim the available space in the old column
1228

1229            if (oldColumn + targetPortlet.getPortletW() <= getColumnCount() ) {
1230                this.findHorizontalEdgeForMoving(oldColumn + targetPortlet.getPortletW() -1, oldRow);
1231                debugDisplayMarkedList("markedColumnList", markedColumnList);
1232                this.moveColumnsUp(targetPortlet.getPortletH(), oldColumn + targetPortlet.getPortletW() -1 );
1233            }
1234
1235            rebuildGridTable();
1236
1237        }
1238    }
1239
1240    /**
1241     * Move the specified portlet one column to the right, creating a new column
1242     * if the portlet is already at the rightmost position before the move.
1243     * @param portletID identifier of the portlet to be moved
1244     * @throws JahiaException if the portlet corresponding to the identifier
1245     * cannot be found
1246     */

1247    public void movePortletRight(int portletID)
1248    throws JahiaException {
1249
1250        PortletBean targetPortlet = findPortlet(portletID);
1251        int oldRow = targetPortlet.getPortletRow();
1252        int oldColumn = targetPortlet.getPortletColumn();
1253        if (oldColumn + targetPortlet.getPortletW() == getColumnCount()) {
1254            // we need to create a new column since the portlet is currently
1255
// in the rightmost column.
1256
columnCount++;
1257            portletTable.setEmptyElementAt(targetPortlet.getPortletRow(), targetPortlet.getPortletColumn()+1);
1258        }
1259
1260        // first we must find insertion point in the right column...
1261

1262        int insertionRow = targetPortlet.getPortletRow();
1263        int insertionColumn = targetPortlet.getPortletColumn() + 1;
1264        /* Let's check if we are inserting in a column that is smaller than
1265           the current row position. If so reduce the row to include at the
1266           end of the column, avoiding "hole" creation.
1267         */

1268        if (targetPortlet.getPortletRow() >= getRowCountWithoutPortlet(targetPortlet.getPortletColumn() + 1, targetPortlet.getPortletID()) ) {
1269            insertionRow = getRowCountWithoutPortlet(targetPortlet.getPortletColumn() + 1, targetPortlet.getPortletID());
1270        } else {
1271            PortletBean testPortlet = null;
1272            if ( areCoordinatesValid(targetPortlet.getPortletRow(),
1273                                     targetPortlet.getPortletColumn()+targetPortlet.getPortletW())) {
1274                testPortlet = (PortletBean) this.portletTable.getElementAt(targetPortlet.getPortletRow(),
1275                                                                           targetPortlet.getPortletColumn()+targetPortlet.getPortletW());
1276            }
1277            if (testPortlet != null) {
1278                if (testPortlet.getPortletRow() == targetPortlet.getPortletRow() ) {
1279                    // both portlets start on the same row, all we need to
1280
// know not is if the test portlet starts on the previous
1281
// column or not...
1282
if (testPortlet.getPortletColumn() != targetPortlet.getPortletColumn() + 1) {
1283                        // destination column is not where the test portlet
1284
// starts...
1285
insertionColumn = testPortlet.getPortletColumn();
1286                    }
1287                } else {
1288                    // portlets don't start on the same row, let's insert
1289
// immediately below the test portlet.
1290
insertionRow = testPortlet.getPortletRow() + testPortlet.getPortletH();
1291                    // insertionColumn = testPortlet.getPortletColumn();
1292
}
1293            }
1294
1295        }
1296
1297        // now let's make room in the new column
1298
boolean enoughFreeSpace = true;
1299        for (int i=0; i < targetPortlet.getPortletH(); i++) {
1300            PortletBean tempPortlet = null;
1301            if ( areCoordinatesValid(insertionRow + i,
1302                                     targetPortlet.getPortletColumn()+targetPortlet.getPortletW()) ) {
1303                tempPortlet = (PortletBean) portletTable.getElementAt(insertionRow + i,
1304                                                                      targetPortlet.getPortletColumn()+targetPortlet.getPortletW());
1305            }
1306            if (tempPortlet != null) {
1307                enoughFreeSpace = false;
1308                break;
1309            }
1310        }
1311        if (!enoughFreeSpace) {
1312            /** @todo we might need to iterate over width of portlet here */
1313            for (int i=0; i < targetPortlet.getPortletW(); i++) {
1314                this.findHorizontalEdgeForMoving(insertionColumn+i, insertionRow);
1315            }
1316            this.moveColumnsDown(targetPortlet.getPortletH());
1317        }
1318
1319        // let's set the new position
1320
targetPortlet.setPortletRow(insertionRow);
1321        targetPortlet.setPortletColumn(targetPortlet.getPortletColumn()+1);
1322
1323        rebuildGridTable();
1324
1325        // and let's reclaim the available space in the old column
1326

1327        if (oldColumn < getColumnCount() ) {
1328            this.findHorizontalEdgeForMoving(oldColumn, oldRow + targetPortlet.getPortletH());
1329            this.debugDisplayMarkedList("markedColumnList", markedColumnList);
1330            this.moveColumnsUp(targetPortlet.getPortletH(), oldColumn);
1331        }
1332
1333        rebuildGridTable();
1334    }
1335
1336    // The next few methods concern portlet swapping left/right and up/down
1337
// This has been added because we cannot always swap but we might want to
1338
// in simple situations.
1339

1340    /** @todo FIXME is there a way to regroup all these methods into one ?
1341     * Would sure make this a LOT less ugly !
1342     */

1343
1344    /**
1345     * Returns true if we can swap the portlet upwards
1346     * @param portletID the identifier of the portlet to swap. If the portlet
1347     * ID does not exist, this method will simply return false.
1348     * @return true if we can swap, false if we cannot.
1349     */

1350    public boolean canSwapPortletUp(int portletID) {
1351        PortletBean targetPortlet = null;
1352        try {
1353            targetPortlet = findPortlet(portletID);
1354        } catch (JahiaException je) {
1355            return false;
1356        }
1357        if (targetPortlet.getPortletRow() == 0) {
1358            // already at the top, do nothing
1359
return false;
1360        }
1361        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() - 1,
1362                                                                            targetPortlet.getPortletColumn());
1363        if (portletToSwap != null) {
1364            // now we must check if these portlets has the same width, in
1365
// which case we just swap them.
1366
if ( (portletToSwap.getPortletRow() == targetPortlet.getPortletRow() - portletToSwap.getPortletH()) &&
1367                 (portletToSwap.getPortletColumn() == targetPortlet.getPortletColumn()) ) {
1368                // we do this swap only if the starting positions are the same
1369
if (targetPortlet.getPortletW() == portletToSwap.getPortletW() ) {
1370                    return true;
1371                }
1372            }
1373        }
1374        return false;
1375    }
1376
1377    /**
1378     * Returns true if we can swap the portlet downwards
1379     * @param portletID the identifier of the portlet to swap. If the portlet
1380     * ID does not exist, this method will simply return false.
1381     * @return true if we can swap, false if we cannot.
1382     */

1383    public boolean canSwapPortletDown(int portletID) {
1384        PortletBean targetPortlet = null;
1385        try {
1386            targetPortlet = findPortlet(portletID);
1387            if (targetPortlet.getPortletRow() + targetPortlet.getPortletH() == this.getRowCount(targetPortlet.getPortletColumn())) {
1388                // already at the last row...
1389
return false;
1390            }
1391        } catch (JahiaException je) {
1392            return false;
1393        }
1394
1395        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + targetPortlet.getPortletH(),
1396                                                                            targetPortlet.getPortletColumn());
1397        if (portletToSwap != null) {
1398            // now we must check if these portlets has the same width, in
1399
// which case we just swap them.
1400
if (targetPortlet.getPortletW() == portletToSwap.getPortletW() ) {
1401                return true;
1402            }
1403        }
1404        return false;
1405    }
1406
1407    /**
1408     * Returns true if we can swap the portlet left
1409     * @param portletID the identifier of the portlet to swap. If the portlet
1410     * ID does not exist, this method will simply return false.
1411     * @return true if we can swap, false if we cannot.
1412     */

1413    public boolean canSwapPortletLeft(int portletID) {
1414        PortletBean targetPortlet = null;
1415        try {
1416            targetPortlet = findPortlet(portletID);
1417        } catch (JahiaException je) {
1418            return false;
1419        }
1420        if (targetPortlet.getPortletColumn() == 0) {
1421            // already at the top, do nothing
1422
return false;
1423        }
1424        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow(),
1425                                                                            targetPortlet.getPortletColumn() -1);
1426        if (portletToSwap != null) {
1427            // now we must check if these portlets has the same width, in
1428
// which case we just swap them.
1429
if ( (portletToSwap.getPortletColumn() == targetPortlet.getPortletColumn() - portletToSwap.getPortletW()) &&
1430                 (portletToSwap.getPortletRow() == targetPortlet.getPortletRow()) ) {
1431                // we do this swap only if the starting positions are the same
1432
if (targetPortlet.getPortletH() == portletToSwap.getPortletH() ) {
1433                    return true; // operation completed in this case...
1434
}
1435            }
1436        }
1437        return false;
1438    }
1439
1440    /**
1441     * Returns true if we can swap the portlet right
1442     * @param portletID the identifier of the portlet to swap. If the portlet
1443     * ID does not exist, this method will simply return false.
1444     * @return true if we can swap, false if we cannot.
1445     */

1446    public boolean canSwapPortletRight(int portletID) {
1447        PortletBean targetPortlet = null;
1448        try {
1449            targetPortlet = findPortlet(portletID);
1450            if (targetPortlet.getPortletColumn() + targetPortlet.getPortletW() == this.getColumnCount(targetPortlet.getPortletRow())) {
1451                // already at the last row...
1452
return false;
1453            }
1454        } catch (JahiaException je) {
1455            return false;
1456        }
1457
1458        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow(),
1459                                                                            targetPortlet.getPortletColumn() + targetPortlet.getPortletW());
1460        if (portletToSwap != null) {
1461            // now we must check if these portlets has the same width, in
1462
// which case we just swap them. Otherwise we do an insertion
1463
// instead...
1464
if (targetPortlet.getPortletH() == portletToSwap.getPortletH() ) {
1465                return true;
1466            }
1467        }
1468        return false;
1469    }
1470
1471    /**
1472     * Swaps a portlet to the left, if allowed
1473     * @param portletID the identifier of the portlet to swap
1474     * @return true if we could successfully swap the porlet, false if we
1475     * could not
1476     * @throws JahiaException if the portlet could not be found.
1477     */

1478    public boolean swapPortletLeft(int portletID)
1479    throws JahiaException {
1480        if (!canSwapPortletLeft(portletID)) {
1481            return false;
1482        }
1483        PortletBean targetPortlet = findPortlet(portletID);
1484        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow(),
1485                                                                            targetPortlet.getPortletColumn() - 1);
1486        int swapColumn = portletToSwap.getPortletColumn();
1487        portletToSwap.setPortletColumn(swapColumn + targetPortlet.getPortletW());
1488        targetPortlet.setPortletColumn(swapColumn);
1489        rebuildGridTable();
1490        return true;
1491
1492    }
1493
1494    /**
1495     * Swaps a portlet to the right, if allowed
1496     * @param portletID the identifier of the portlet to swap
1497     * @return true if we could successfully swap the porlet, false if we
1498     * could not
1499     * @throws JahiaException if the portlet could not be found.
1500     */

1501    public boolean swapPortletRight(int portletID)
1502    throws JahiaException {
1503        if (!canSwapPortletRight(portletID)) {
1504            return false;
1505        }
1506        PortletBean targetPortlet = findPortlet(portletID);
1507
1508        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow(),
1509                                                                            targetPortlet.getPortletColumn() + targetPortlet.getPortletW());
1510        int swapColumn = targetPortlet.getPortletColumn();
1511        portletToSwap.setPortletColumn(swapColumn);
1512        targetPortlet.setPortletColumn(swapColumn + targetPortlet.getPortletW());
1513        rebuildGridTable();
1514        return true;
1515    }
1516
1517    /**
1518     * Swaps a portlet up, if allowed
1519     * @param portletID the identifier of the portlet to swap
1520     * @return true if we could successfully swap the porlet, false if we
1521     * could not
1522     * @throws JahiaException if the portlet could not be found.
1523     */

1524    public boolean swapPortletUp(int portletID)
1525    throws JahiaException {
1526        if (!canSwapPortletUp(portletID)) {
1527            return false;
1528        }
1529        PortletBean targetPortlet = findPortlet(portletID);
1530        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() - 1,
1531                                                                            targetPortlet.getPortletColumn());
1532        int swapRow = portletToSwap.getPortletRow();
1533        portletToSwap.setPortletRow(swapRow + targetPortlet.getPortletH());
1534        targetPortlet.setPortletRow(swapRow);
1535        rebuildGridTable();
1536        return true;
1537    }
1538
1539    /**
1540     * Swaps a portlet down, if allowed
1541     * @param portletID the identifier of the portlet to swap
1542     * @return true if we could successfully swap the porlet, false if we
1543     * could not
1544     * @throws JahiaException if the portlet could not be found.
1545     */

1546    public boolean swapPortletDown(int portletID)
1547    throws JahiaException {
1548        if (!canSwapPortletDown(portletID)) {
1549            return false;
1550        }
1551        PortletBean targetPortlet = findPortlet(portletID);
1552        PortletBean portletToSwap = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + targetPortlet.getPortletH(),
1553                                                                            targetPortlet.getPortletColumn());
1554        int swapRow = targetPortlet.getPortletRow();
1555        portletToSwap.setPortletRow(swapRow);
1556        targetPortlet.setPortletRow(swapRow + targetPortlet.getPortletH());
1557        rebuildGridTable();
1558        return true;
1559    }
1560
1561    /**
1562     * Increase the height of the specified portlet. No upper limit is defined.
1563     * This will mostly be used for col span implemenations in display JSPs
1564     * @param portletID identifier of the portlet to modify
1565     */

1566    public void IncreaseHeight(int portletID)
1567    throws JahiaException {
1568        PortletBean targetPortlet = findPortlet(portletID);
1569        int currentHeight = targetPortlet.getPortletH();
1570        int currentWidth = targetPortlet.getPortletW();
1571        // before we increase the height, we must first make room for it by
1572
// making or using free space. If there isn't enough free space we mark
1573
// the columns for a down move...
1574
boolean enoughFreeSpace = true;
1575        if (targetPortlet.getPortletRow() + currentHeight < getRowCount() ) {
1576            // we only check if we are inside grid space, otherwise we have room
1577
// anyhow...
1578
for (int i=0; i < currentWidth; i++) {
1579                PortletBean tempPortlet = null;
1580                if ( areCoordinatesValid(targetPortlet.getPortletRow() + currentHeight,
1581                                         targetPortlet.getPortletColumn()+i) ) {
1582                    tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + currentHeight,
1583                                                                          targetPortlet.getPortletColumn()+i);
1584                }
1585                if (tempPortlet != null) {
1586                    enoughFreeSpace = false;
1587                    this.findHorizontalEdgeForMoving(targetPortlet.getPortletColumn()+i,
1588                                                     targetPortlet.getPortletRow() + currentHeight);
1589                }
1590            }
1591        }
1592        if (!enoughFreeSpace) {
1593            debugDisplayMarkedList("markedColumnList", markedColumnList);
1594            this.moveColumnsDown(1);
1595        }
1596        // now that the space is available, let's increase the height.
1597
targetPortlet.setPortletH(currentHeight + 1);
1598        this.rebuildGridTable();
1599    }
1600
1601    /**
1602     * Decrease the height of the specified portlet. A lower limit is zero and
1603     * will not produce any exceptions if reached.
1604     * @param portletID identifier of the portlet to modify
1605     */

1606    public void DecreaseHeight(int portletID)
1607    throws JahiaException {
1608        PortletBean targetPortlet = findPortlet(portletID);
1609        int currentHeight = targetPortlet.getPortletH();
1610        int currentWidth = targetPortlet.getPortletW();
1611        if (currentHeight > 0) {
1612            targetPortlet.setPortletH(currentHeight - 1);
1613        }
1614        this.rebuildGridTable();
1615        // let's tag all the columns for moving up...
1616
for (int i=0; i < currentWidth; i++) {
1617            PortletBean tempPortlet = null;
1618            if ( areCoordinatesValid(targetPortlet.getPortletRow() + currentHeight,
1619                                     targetPortlet.getPortletColumn()+ i) ) {
1620                tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + currentHeight,
1621                                                                      targetPortlet.getPortletColumn()+i);
1622                if (tempPortlet != null) {
1623                    this.findHorizontalEdgeForMoving(targetPortlet.getPortletColumn()+i,
1624                                                     targetPortlet.getPortletRow() + currentHeight);
1625                    this.moveColumnsUp(1, targetPortlet.getPortletColumn()+i);
1626                }
1627            }
1628        }
1629        this.rebuildGridTable();
1630    }
1631
1632    /**
1633     * Increase the width of the specified portlet. No upper limit is defined.
1634     * This will mostly be used for col span implemenations in display JSPs
1635     * @param portletID identifier of the portlet to modify
1636     */

1637    public void IncreaseWidth(int portletID)
1638    throws JahiaException {
1639        PortletBean targetPortlet = findPortlet(portletID);
1640        int currentHeight = targetPortlet.getPortletH();
1641        int currentWidth = targetPortlet.getPortletW();
1642        // before we increase the width, we must first make room for it by
1643
// making or using free space. If there isn't enough free space we mark
1644
// the rows for a right move...
1645
boolean enoughFreeSpace = true;
1646        if (targetPortlet.getPortletColumn() + currentWidth < getColumnCount() ) {
1647            // we only check if we are in grid... if not we have enough room anyway
1648
for (int i=0; i < currentHeight; i++) {
1649                PortletBean tempPortlet = null;
1650                if ( areCoordinatesValid(targetPortlet.getPortletRow() + i,
1651                                         targetPortlet.getPortletColumn()+ currentWidth) ) {
1652                    tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + i,
1653                                                                          targetPortlet.getPortletColumn()+ currentWidth);
1654                }
1655                if (tempPortlet != null) {
1656                    enoughFreeSpace = false;
1657                    this.findVerticalEdgeForMoving(targetPortlet.getPortletRow() +i,
1658                                                   targetPortlet.getPortletColumn()+ currentWidth);
1659                }
1660            }
1661        }
1662        if (!enoughFreeSpace) {
1663            debugDisplayMarkedList("markedRowList", markedRowList);
1664            this.moveRowsRight(1);
1665        }
1666        // now that the space is available, let's increase the width.
1667
targetPortlet.setPortletW(currentWidth + 1);
1668        this.rebuildGridTable();
1669
1670    }
1671
1672    /**
1673     * Decrease the width of the specified portlet. A lower limit is zero and
1674     * will not produce any exceptions if reached.
1675     * @param portletID identifier of the portlet to modify
1676     */

1677    public void DecreaseWidth(int portletID)
1678    throws JahiaException {
1679        PortletBean targetPortlet = findPortlet(portletID);
1680        int currentHeight = targetPortlet.getPortletH();
1681        int currentWidth = targetPortlet.getPortletW();
1682        if (currentWidth > 0) {
1683            targetPortlet.setPortletW(currentWidth - 1);
1684        }
1685        rebuildGridTable();
1686        // now that we've decreased the width, let's tag all the rows for moving
1687
// left...
1688
for (int i=0; i < currentHeight; i++) {
1689            if (areCoordinatesValid(targetPortlet.getPortletRow()+i,
1690                                    targetPortlet.getPortletColumn() + currentWidth) ) {
1691                PortletBean tempPortlet = (PortletBean) portletTable.getElementAt(targetPortlet.getPortletRow() + i,
1692                                                                                  targetPortlet.getPortletColumn()+ currentWidth);
1693                if (tempPortlet != null) {
1694                    this.findVerticalEdgeForMoving(targetPortlet.getPortletRow() + i,
1695                                                   targetPortlet.getPortletColumn()+ currentWidth);
1696                    this.debugDisplayMarkedList("markedRowList", markedRowList);
1697                    this.moveRowsLeft(1, targetPortlet.getPortletRow()+i);
1698                }
1699            }
1700        }
1701        this.rebuildGridTable();
1702    }
1703
1704
1705    /**
1706     * Displays the grid on the jahia console by inserting the portlet ID into
1707     * each cell.
1708     *
1709     * This is *almost* the same version as the one in PortletBeanGrid except
1710     * that we're accessing the reference table here...
1711     */

1712    public void debugDisplayGrid() {
1713        String JavaDoc separatorLine = new String JavaDoc();
1714        for (int j=0; j < this.getColumnCount(); j++) {
1715            separatorLine = separatorLine + "+-----";
1716        }
1717
1718        StringBuffer JavaDoc curLine;
1719        String JavaDoc idStr = "";
1720        for (int i=0; i < this.getRowCount(); i++) {
1721            curLine = new StringBuffer JavaDoc();
1722            curLine = new StringBuffer JavaDoc();
1723            for (int j=0; j < this.getColumnCount(); j++) {
1724                PortletBean curPortlet = this.getPortletFromRefTable(i, j);
1725                curLine.append("�");
1726                if (curPortlet != null) {
1727                    idStr = Integer.toString(curPortlet.getPortletID());
1728                    while (idStr.length() < 5) {
1729                        idStr = " " + idStr;
1730                    }
1731                } else {
1732                    idStr = " null";
1733                }
1734                curLine.append(idStr);
1735            }
1736            JahiaConsole.println("PortletBeanGrid.debugDisplayGrid", separatorLine);
1737            JahiaConsole.println("PortletBeanGrid.debugDisplayGrid",
1738                                 curLine.toString());
1739        }
1740    }
1741
1742
1743    /**
1744     * Checks if the passed coordinate are a valid position in the grid.
1745     * @param row X coordinate to test
1746     * @param column Y coordinate to test
1747     * @returns true if the coordinates are an existing valid grid position. This
1748     * will not extend the grid to fit the coordinates. false is returned
1749     * otherwise :)
1750     */

1751    private boolean areCoordinatesValid(int row, int column) {
1752        if (isRowCoordinateValid(row) && isColumnCoordinateValid(column) ) {
1753            return true;
1754        }
1755        return false;
1756    }
1757
1758    /**
1759     * Checks if the passed row coordinate is a valid position in the grid.
1760     * @param row X coordinate to test
1761     * @returns true if the coordinate is an existing valid row grid position.
1762     * This will not extend the grid to fit the coordinates. false is returned
1763     * otherwise :)
1764     */

1765    private boolean isRowCoordinateValid(int row) {
1766        if ((row >= 0) && (row < portletTable.getRowCount())) {
1767            return true;
1768        }
1769        return false;
1770    }
1771
1772    /**
1773     * Checks if the passed column coordinate is a valid position in the grid.
1774     * @param column Y coordinate to test
1775     * @returns true if the coordinate is an existing valid column grid position.
1776     * This will not extend the grid to fit the coordinates. false is returned
1777     * otherwise :)
1778     */

1779    private boolean isColumnCoordinateValid(int column) {
1780        if ((column >= 0) && (column < portletTable.getColumnCount())) {
1781            return true;
1782        }
1783        return false;
1784    }
1785
1786
1787}
Popular Tags