001: package com.xoetrope.carousel.builder;
002:
003: import com.xoetrope.swing.XTreeTable;
004: import com.xoetrope.swing.table.XCheckBoxTableCellRenderer;
005: import java.awt.BorderLayout;
006: import java.awt.CardLayout;
007: import java.awt.Color;
008: import java.awt.Container;
009: import java.awt.FlowLayout;
010: import java.awt.Point;
011: import java.awt.Rectangle;
012: import java.awt.event.ActionEvent;
013: import java.awt.event.ActionListener;
014: import java.util.ArrayList;
015: import java.util.HashMap;
016: import java.util.List;
017: import java.util.Map;
018: import javax.swing.AbstractButton;
019: import javax.swing.BorderFactory;
020: import javax.swing.BoxLayout;
021: import javax.swing.ImageIcon;
022: import javax.swing.JButton;
023: import javax.swing.JCheckBox;
024: import javax.swing.JComponent;
025: import javax.swing.JDialog;
026: import javax.swing.JFrame;
027: import javax.swing.JLabel;
028: import javax.swing.JPanel;
029: import javax.swing.JScrollPane;
030: import javax.swing.JSpinner;
031: import javax.swing.JTable;
032: import javax.swing.JTextField;
033: import javax.swing.JTree;
034: import javax.swing.JViewport;
035: import javax.swing.SpinnerNumberModel;
036: import javax.swing.SwingConstants;
037: import javax.swing.WindowConstants;
038: import javax.swing.event.ListSelectionEvent;
039: import javax.swing.event.ListSelectionListener;
040: import javax.swing.event.TableModelEvent;
041: import javax.swing.SwingUtilities;
042: import javax.swing.table.DefaultTableCellRenderer;
043: import javax.swing.tree.TreePath;
044: import net.xoetrope.editor.project.XEditorProject;
045: import net.xoetrope.xui.validation.XValidator;
046:
047: /**
048: * A page generator wizard for creating form elements within the editor
049: * <p> Copyright (c) Xoetrope Ltd., 2002-2007</p>
050: * <p> $Revision: 1.77 $</p>
051: * <p> License: see License.txt</p>
052: */
053: public class XFormGeneratorWizard extends JDialog implements
054: ActionListener {
055: private static String[] componentItems = { "<none>", "Label",
056: "Edit", "Combo", "Audio", "Calendar", "CheckBox",
057: "CheckedCombo", "CheckList", "Date", "Image", "ImageMap",
058: "List", "Money", "Table", "TextArea", "Tree", "Password",
059: "ProgressBar", "RadioButton", "Shape", "Spinner",
060: "ReflectedImage", "Video" };
061:
062: private static String[] validationItems = { "<none>", "MinMax",
063: "Date", "Name", "Password", "RegEx", "Set" };
064:
065: private XFormGeneratorInfo formGeneratorInfo;
066: private JButton nextBtn, prevBtn, upBtn, downBtn;
067: private Object lastBtn;
068: private JScrollPane jScrollPane1;
069: private XTreeTable table;
070: private JPanel fieldPanel, layoutPanel;
071: private CardLayout cardManager;
072:
073: private JSpinner colWidthSpinner;
074: private JLabel jLabel1;
075: private JLabel jLabel2;
076: private JLabel jLabel3;
077: private JLabel jLabel4;
078: private JLabel jLabel5;
079: private JLabel jLabel6;
080: private JLabel jLabel7, jLabel8;
081: private JLabel alphaWarning;
082: private JSpinner numColsSpinner;
083: private JSpinner paddingSpinner;
084: private JSpinner panelPaddingSpinner;
085: private JTextField panelTitle;
086: private JSpinner rowHeightSpinner;
087: private JSpinner suffixWidthSpinner;
088: private JSpinner panelArcSpinner;
089: private JCheckBox panelOpaque;
090:
091: private int cardIdx;
092: private JPanel cardPanel, buttonPanel;
093:
094: private XEditorProject currentProject;
095:
096: /**
097: * Creates a new instance of XFormGeneratorWizard
098: */
099: public XFormGeneratorWizard(XEditorProject project,
100: XFormGeneratorInfo model) {
101: super ((JFrame) null, true);
102:
103: currentProject = project;
104:
105: formGeneratorInfo = model;
106: initComponents();
107: setTitle("Form Generation");
108: cardIdx = 0;
109: }
110:
111: public boolean showDialog() {
112: setupProperties();
113: setVisible(true);
114:
115: return (lastBtn == nextBtn);
116: }
117:
118: /*** code for storing the information about expanded nodes ******************/
119:
120: /**
121: * Expand the table's nodes stored in the specified TreeTableNode object.
122: * @param rootNode the root of the tree containing nodes to be expanded.
123: */
124: private void expandNodes(TreeTableNode rootNode) {
125: for (TreeTableNode childNode : rootNode.children)
126: expandNodes(childNode, 0);
127: }
128:
129: /**
130: * Expands the table's nodes stored in the specified subtree.
131: * @param node the root of a subtree containing nodes to be expanded.
132: * @param level distance between the root node and the specified node.
133: */
134: private void expandNodes(TreeTableNode node, int level) {
135: if (node.isExpanded()) {
136: table.setSelection(node.rowNr + level);
137: for (TreeTableNode childNode : node.children)
138: expandNodes(childNode, node.rowNr + level);
139: }
140: }
141:
142: /**
143: * Stores the information about the currently expanded nodes
144: * in the given ExpandedNode object
145: */
146: private void storeExpandedNodes(TreeTableNode rootNode) {
147: storeExpandedNodes(rootNode, 0, formGeneratorInfo);
148: }
149:
150: // internal, traverse the tree and and stores informations about expanded nodes
151: private int storeExpandedNodes(TreeTableNode currentNode,
152: int tableIndex, XFormGeneratorInfo formInfo) {
153: while (sameLevel(tableIndex, formInfo)) {
154:
155: XFormGeneratorInfo childInfo = getChildFormInfo(tableIndex,
156: formInfo);
157:
158: TreeTableNode childNode = currentNode.addChild(tableIndex);
159: if (sameLevel(tableIndex + 1, childInfo)) // this means that the node is expanded
160: tableIndex = storeExpandedNodes(childNode,
161: tableIndex + 1, childInfo);
162: else
163: tableIndex++;
164: }
165:
166: return tableIndex;
167: }
168:
169: /**
170: * Gets the field's name at the specified table's node.
171: * @param idx the number of the table's row.
172: * @return the name of the field.
173: */
174: private String getTableFieldName(int idx) {
175: return (String) table.getValue(idx, 0);
176: }
177:
178: /**
179: * Indicates whether the specified table row is at the same level
180: * as the given XFormGeneratorInfo object.
181: */
182: private boolean sameLevel(int tableIndex,
183: XFormGeneratorInfo formInfo) {
184: if (formInfo == null)
185: return false;
186: if (tableIndex >= table.getRowCount())
187: return false;
188: String tableFieldName = (String) table.getValue(tableIndex, 0);
189: return (formInfo.getProperty(tableFieldName, "name") != null);
190: }
191:
192: private XFormGeneratorInfo getChildFormInfo(int rowIdx,
193: XFormGeneratorInfo formInfo) {
194: String tableFieldName = (String) table.getValue(rowIdx, 0);
195: return (XFormGeneratorInfo) formInfo.getProperty(
196: tableFieldName, "childPanel");
197: }
198:
199: /**
200: * Moves the specified field in the tree table one position up or down.
201: * @param selIdx the position of the field in the tree table.
202: * @param moveUp true - move up, false - move down.
203: */
204: private void moveField(int selIdx, boolean moveUp) {
205: // store the information about expanded nodes
206: final TreeTableNode rootNode = TreeTableNode.createRoot();
207: storeExpandedNodes(rootNode);
208:
209: String fieldName = (String) table.getValue(selIdx, 0);
210:
211: // if the field has been succesfully moved
212: if (formGeneratorInfo.moveField(fieldName, moveUp)) {
213: // update the "treetable nodes" structure
214: final int newIdx = rootNode.moveField(selIdx, moveUp);
215:
216: // refresh the tree table
217: table.tableChanged(new TableModelEvent(formGeneratorInfo));
218: table.reload();
219:
220: // expand the nodes that had been expanded before the field was moved
221: SwingUtilities.invokeLater(new Runnable() {
222: public void run() {
223: expandNodes(rootNode);
224:
225: // make the selected row visible
226: JTree tree = table.getTree();
227: TreePath selectedPath = tree.getPathForRow(newIdx);
228: tree.scrollPathToVisible(selectedPath);
229: Rectangle rect = table.getCellRect(newIdx, 0, true);
230: Container p = table.getParent();
231: if (p instanceof JViewport)
232: ((JViewport) p).setViewPosition(new Point(
233: rect.x, Math.max(0, rect.y
234: - ((JScrollPane) p.getParent())
235: .getHeight() / 2)));
236:
237: table.setRowSelectionInterval(newIdx, newIdx);
238: }
239: });
240: }
241: }
242:
243: public void actionPerformed(ActionEvent ae) {
244: lastBtn = ae.getSource();
245: int selIdx = table.getSelectedRow();
246:
247: if (lastBtn == upBtn) {
248: moveField(selIdx, true);
249: return;
250: } else if (lastBtn == downBtn) {
251: moveField(selIdx, false);
252: return;
253: }
254:
255: if (lastBtn == nextBtn) {
256: if (cardIdx == 1) {
257: setVisible(false);
258: saveProperties();
259: } else {
260: prevBtn.setText("Prev");
261: nextBtn.setText("Finish");
262: prevBtn
263: .setIcon(new ImageIcon(
264: getClass()
265: .getResource(
266: "/com/xoetrope/carousel/resources/go-previous.png")));
267: nextBtn
268: .setIcon(new ImageIcon(
269: getClass()
270: .getResource(
271: "/com/xoetrope/carousel/resources/go-jump.png")));
272: cardManager.next(cardPanel);
273: cardIdx++;
274: lastBtn = null;
275: }
276: } else {
277: if (cardIdx == 0)
278: setVisible(false);
279: else {
280: prevBtn.setText("Cancel");
281: nextBtn.setText("Next");
282: prevBtn
283: .setIcon(new ImageIcon(
284: getClass()
285: .getResource(
286: "/com/xoetrope/carousel/resources/user-trash-full.png")));
287: nextBtn
288: .setIcon(new ImageIcon(
289: getClass()
290: .getResource(
291: "/com/xoetrope/carousel/resources/go-next.png")));
292: cardManager.previous(cardPanel);
293: }
294: cardIdx--;
295: }
296: }
297:
298: private void saveProperties() {
299: formGeneratorInfo.setGenerationParameter("rowHeight",
300: rowHeightSpinner.getValue().toString());
301: formGeneratorInfo.setGenerationParameter("colWidth",
302: colWidthSpinner.getValue().toString());
303: formGeneratorInfo.setGenerationParameter("padding",
304: paddingSpinner.getValue().toString());
305: formGeneratorInfo.setGenerationParameter("panelPadding",
306: panelPaddingSpinner.getValue().toString());
307: formGeneratorInfo.setGenerationParameter("numColumns",
308: numColsSpinner.getValue().toString());
309: formGeneratorInfo.setGenerationParameter("suffixWidth",
310: suffixWidthSpinner.getValue().toString());
311: formGeneratorInfo.setGenerationParameter("panelArc",
312: panelArcSpinner.getValue().toString());
313: formGeneratorInfo.setGenerationParameter("panelOpaque",
314: panelOpaque.isSelected() ? "true" : "false");
315: }
316:
317: private void setupProperties() {
318: panelTitle.setText(formGeneratorInfo
319: .getGenerationParameter("title"));
320: rowHeightSpinner.setModel(new SpinnerNumberModel(
321: XFormGenerator.ROW_HEIGHT, 5, 50, 1));
322: colWidthSpinner.setModel(new SpinnerNumberModel(
323: XFormGenerator.COL_WIDTH, 30, 2000, 2));
324: paddingSpinner.setModel(new SpinnerNumberModel(
325: XFormGenerator.PADDING, 0, 50, 1));
326: panelPaddingSpinner.setModel(new SpinnerNumberModel(
327: XFormGenerator.PANEL_PADDING, 0, 50, 1));
328: numColsSpinner.setModel(new SpinnerNumberModel(1, 1, 50, 1));
329: suffixWidthSpinner
330: .setModel(new SpinnerNumberModel(0, 0, 50, 1));
331:
332: rowHeightSpinner.setValue(Integer.parseInt(formGeneratorInfo
333: .getGenerationParameter("rowHeight")));
334: colWidthSpinner.setValue(Integer.parseInt(formGeneratorInfo
335: .getGenerationParameter("colWidth")));
336: paddingSpinner.setValue(Integer.parseInt(formGeneratorInfo
337: .getGenerationParameter("padding")));
338: panelPaddingSpinner.setValue(Integer.parseInt(formGeneratorInfo
339: .getGenerationParameter("panelPadding")));
340: numColsSpinner.setValue(Integer.parseInt(formGeneratorInfo
341: .getGenerationParameter("numColumns")));
342: suffixWidthSpinner.setValue(Integer.parseInt(formGeneratorInfo
343: .getGenerationParameter("suffixWidth")));
344: panelArcSpinner.setValue(Integer.parseInt(formGeneratorInfo
345: .getGenerationParameter("panelArc")));
346: panelOpaque.setSelected("true".equals("panelOpaque"));
347: }
348:
349: /** This method is called from within the constructor to
350: * initialize the form.
351: * WARNING: Do NOT modify this code. The content of this method is
352: * always regenerated by the Form Editor.
353: */
354: private void initComponents() {
355: setSize(864, 425);
356:
357: cardPanel = new JPanel();
358: buttonPanel = new JPanel();
359: buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
360: fieldPanel = new JPanel();
361: fieldPanel.setLayout(new BorderLayout(2, 2));
362: fieldPanel.setSize(750, 379);
363: layoutPanel = new JPanel();
364: layoutPanel.setLayout(null);
365: layoutPanel.setSize(750, 379);
366: cardManager = new CardLayout(10, 10);
367:
368: JPanel contentPanel = (JPanel) getContentPane();
369: cardPanel.setLayout(cardManager);
370: cardPanel.add(fieldPanel, "fields");
371: cardPanel.add(layoutPanel, "layout");
372: cardManager.show(cardPanel, "fields");
373:
374: jScrollPane1 = new JScrollPane();
375: fieldPanel.add(jScrollPane1, BorderLayout.CENTER);
376: nextBtn = new JButton();
377: prevBtn = new JButton();
378: upBtn = new JButton();
379: downBtn = new JButton();
380: upBtn.setIcon(new ImageIcon(getClass().getResource(
381: "/com/xoetrope/carousel/resources/go-up.png")));
382: downBtn.setIcon(new ImageIcon(getClass().getResource(
383: "/com/xoetrope/carousel/resources/go-down.png")));
384: contentPanel.add(cardPanel, BorderLayout.CENTER);
385: contentPanel.add(buttonPanel, BorderLayout.SOUTH);
386: buttonPanel.add(prevBtn);
387: buttonPanel.add(nextBtn);
388:
389: prevBtn.setBounds(340, 390, 100, 30);
390: nextBtn.setBounds(450, 390, 100, 30);
391:
392: JPanel navBtnPane1 = new JPanel();
393: fieldPanel.add(navBtnPane1, BorderLayout.EAST);
394: navBtnPane1.setLayout(new BoxLayout(navBtnPane1,
395: BoxLayout.Y_AXIS));
396: navBtnPane1.add(upBtn);
397: navBtnPane1.add(downBtn);
398: upBtn.setEnabled(false);
399: downBtn.setEnabled(false);
400:
401: nextBtn.addActionListener(this );
402: prevBtn.addActionListener(this );
403: upBtn.addActionListener(this );
404: downBtn.addActionListener(this );
405:
406: setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
407: table = new XTreeTable();
408:
409: XCheckBoxTableCellRenderer booleanRenderer = new XCheckBoxTableCellRenderer();
410: XCheckBoxTableCellRenderer booleanEditor = new XCheckBoxTableCellRenderer();
411: XFormComboTableCellRenderer compRenderer = new XFormComboTableCellRenderer(
412: componentItems);
413:
414: String listItems[] = currentProject.getValidations();
415: int len = listItems.length;
416: String[] validations = new String[1 + len];
417: System.arraycopy(listItems, 0, validations, 1, len);
418: validations[0] = "[None]";
419:
420: XFormComboTableCellRenderer validationRenderer = new XFormComboTableCellRenderer(
421: validations);
422:
423: table.setDefaultRenderer(Boolean.class, booleanRenderer);
424: table.setDefaultEditor(Boolean.class, booleanEditor);
425:
426: table.setDefaultEditor(JComponent.class, compRenderer);
427:
428: table.setDefaultRenderer(XValidator.class,
429: new DefaultTableCellRenderer());
430: table.setDefaultEditor(XValidator.class, validationRenderer);
431:
432: List<String> propertyList = formGeneratorInfo.getPropertyList();
433: Map<String, Object> fieldProperties = new HashMap();
434: fieldProperties.put("childPanel", formGeneratorInfo);
435: table.setModel(new XFormInfoTreeTableAdapter(propertyList,
436: fieldProperties), formGeneratorInfo);
437:
438: table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
439: jScrollPane1.setViewportView(table);
440:
441: table.getSelectionModel().addListSelectionListener(
442: new ListSelectionListener() {
443: public void valueChanged(ListSelectionEvent e) {
444: int selIdx = table.getSelectedRow();
445: int maxIdx = table.getRowCount() - 1;
446: if (selIdx < 0) {
447: upBtn.setEnabled(false);
448: downBtn.setEnabled(false);
449: } else {
450: upBtn.setEnabled(selIdx > 0);
451: downBtn.setEnabled(selIdx < maxIdx);
452: }
453: }
454: });
455:
456: nextBtn.setIcon(new ImageIcon(getClass().getResource(
457: "/com/xoetrope/carousel/resources/go-next.png")));
458: nextBtn.setText("Next"); // NOI18N
459:
460: prevBtn
461: .setIcon(new ImageIcon(
462: getClass()
463: .getResource(
464: "/com/xoetrope/carousel/resources/user-trash-full.png")));
465: prevBtn.setText("Cancel");
466:
467: // Layout panel
468: panelTitle = new JTextField();
469: jLabel1 = new JLabel("Title");
470: layoutPanel.add(panelTitle);
471: jLabel2 = new JLabel("Row Height");
472: rowHeightSpinner = new JSpinner();
473: jLabel3 = new JLabel("Column Width");
474: colWidthSpinner = new JSpinner();
475: jLabel4 = new JLabel("Padding");
476: paddingSpinner = new JSpinner();
477: jLabel5 = new JLabel("Number of Columns");
478: numColsSpinner = new JSpinner();
479: suffixWidthSpinner = new JSpinner();
480: jLabel6 = new JLabel("Suffix Width");
481:
482: jLabel7 = new JLabel("Panel Padding");
483: panelPaddingSpinner = new JSpinner();
484:
485: panelArcSpinner = new JSpinner();
486: jLabel8 = new JLabel("Panel Rounding");
487:
488: panelOpaque = new JCheckBox("Panel Opaque");
489:
490: layoutPanel.add(panelTitle);
491: layoutPanel.add(rowHeightSpinner);
492: layoutPanel.add(colWidthSpinner);
493: layoutPanel.add(paddingSpinner);
494: layoutPanel.add(numColsSpinner);
495: layoutPanel.add(suffixWidthSpinner);
496: layoutPanel.add(panelPaddingSpinner);
497: layoutPanel.add(panelArcSpinner);
498: layoutPanel.add(panelOpaque);
499:
500: layoutPanel.add(jLabel1);
501: layoutPanel.add(jLabel2);
502: layoutPanel.add(jLabel3);
503: layoutPanel.add(jLabel4);
504: layoutPanel.add(jLabel5);
505: layoutPanel.add(jLabel6);
506: layoutPanel.add(jLabel7);
507: layoutPanel.add(jLabel8);
508:
509: alphaWarning = new JLabel(
510: "Warning: This is an early access feature - use at your discretion");
511: alphaWarning.setHorizontalAlignment(SwingConstants.RIGHT);
512: alphaWarning.setForeground(Color.gray);
513: alphaWarning.setBounds(400, 300, 400, 20);
514: layoutPanel.add(alphaWarning);
515:
516: panelTitle.setBounds(120, 10, 100, 20);
517: rowHeightSpinner.setBounds(120, 34, 100, 20);
518: colWidthSpinner.setBounds(120, 58, 100, 20);
519: paddingSpinner.setBounds(120, 82, 100, 20);
520: numColsSpinner.setBounds(120, 106, 100, 20);
521: suffixWidthSpinner.setBounds(120, 130, 100, 20);
522: panelPaddingSpinner.setBounds(120, 154, 100, 20);
523: panelArcSpinner.setBounds(120, 178, 100, 20);
524: panelOpaque.setBounds(14, 202, 124, 20);
525: panelOpaque.setHorizontalTextPosition(AbstractButton.LEADING);
526: panelOpaque.setHorizontalAlignment(AbstractButton.RIGHT);
527:
528: jLabel1.setBounds(14, 10, 100, 20);
529: jLabel2.setBounds(14, 34, 100, 20);
530: jLabel3.setBounds(14, 58, 100, 20);
531: jLabel4.setBounds(14, 82, 100, 20);
532: jLabel5.setBounds(14, 106, 100, 20);
533: jLabel6.setBounds(14, 130, 100, 20);
534: jLabel7.setBounds(14, 154, 100, 20);
535: jLabel8.setBounds(14, 178, 100, 20);
536:
537: setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
538: layoutPanel.setBorder(BorderFactory.createEtchedBorder());
539: jLabel1.setHorizontalAlignment(SwingConstants.RIGHT);
540: jLabel2.setHorizontalAlignment(SwingConstants.RIGHT);
541: jLabel3.setHorizontalAlignment(SwingConstants.RIGHT);
542: jLabel4.setHorizontalAlignment(SwingConstants.RIGHT);
543: jLabel5.setHorizontalAlignment(SwingConstants.RIGHT);
544: jLabel6.setHorizontalAlignment(SwingConstants.RIGHT);
545: jLabel7.setHorizontalAlignment(SwingConstants.RIGHT);
546: jLabel8.setHorizontalAlignment(SwingConstants.RIGHT);
547: }
548:
549: }
550:
551: /** Stores informations about expanded TreeTable nodes */
552: class TreeTableNode {
553: // a relative row number
554: int rowNr;
555: // parent node
556: TreeTableNode parent;
557: // list of first-level children (the order is preserved)
558: List<TreeTableNode> children;
559:
560: /**
561: * Creates a new root.
562: * @return the new root
563: */
564: static TreeTableNode createRoot() {
565: return new TreeTableNode(0, null);
566: }
567:
568: /**
569: * Creates a new instance of TreeTableNode
570: * @param aRowNr associated row in the tree table
571: * @param aParent parent node
572: */
573: private TreeTableNode(int aRowNr, TreeTableNode aParent) {
574: rowNr = aRowNr;
575: parent = aParent;
576: children = new ArrayList();
577: }
578:
579: /**
580: * Adds a new child to this node
581: * @param aRowNr associated row number in the table
582: * @return new child node
583: */
584: TreeTableNode addChild(int aRowNr) {
585: int relRowNr = aRowNr - getAbsDeep();
586: TreeTableNode childNode = new TreeTableNode(relRowNr, this );
587: children.add(childNode);
588: return childNode;
589: }
590:
591: /**
592: * Indicates whether this treeTable node is expanded.
593: * @return true if expanded, false otherwise
594: */
595: public boolean isExpanded() {
596: return (children.size() > 0);
597: }
598:
599: /**
600: * Moves the specified row up/down
601: * @param aRowNr the number of the row to be moved
602: * @param moveUp true - move up, false - move down
603: * @return the new position in the table
604: */
605: int moveField(int aRowNr, boolean moveUp) {
606: int numChildren = children.size();
607: for (int i = 0; i < numChildren; i++) {
608: TreeTableNode currentChild = children.get(i);
609:
610: // we found the right row
611: if (currentChild.rowNr == aRowNr)
612: return switchChildren(i, i + (moveUp ? -1 : 1));
613:
614: TreeTableNode nextChild = (i + 1 < numChildren ? children
615: .get(i + 1) : null);
616: // the required node is in the currentChild's subtree.
617: if ((nextChild == null) || (currentChild.rowNr < aRowNr)
618: && (nextChild.rowNr > aRowNr))
619: return (currentChild.rowNr + currentChild.moveField(
620: aRowNr - currentChild.rowNr, moveUp));
621: }
622:
623: return aRowNr; // row not found;
624: }
625:
626: /**
627: * Swithes the child from the postion idx1 with the one
628: * from the position idx2
629: * @return the new row nr of the child that previously was
630: * located at the idx1 position.
631: */
632: private int switchChildren(int idx1, int idx2) {
633: if ((idx1 < 0) || (idx1 >= children.size()))
634: return children.get(idx1).rowNr;
635: if ((idx2 < 0) || (idx2 >= children.size()))
636: return children.get(idx1).rowNr;
637: TreeTableNode child1 = children.get(idx1);
638: TreeTableNode child2 = children.get(idx2);
639: // switch the positions on the list.
640: children.set(idx1, child2);
641: children.set(idx2, child1);
642:
643: if (idx1 < idx2) { // down
644: child2.rowNr = child1.rowNr;
645: child1.rowNr += child2.countRows();
646: } else { // up
647: child1.rowNr = child2.rowNr;
648: child2.rowNr += child1.countRows();
649: }
650:
651: return child1.rowNr;
652: }
653:
654: /**
655: * Gets the total number of rows rooted at this node
656: * @return total number of rows
657: */
658: private int countRows() {
659: int rowCount = 1;
660: for (TreeTableNode child : children)
661: rowCount += child.countRows();
662: return rowCount;
663: }
664:
665: /**
666: * Gets the distance between root node and this node
667: * @return the distance
668: */
669: private int getAbsDeep() {
670: int dist = rowNr;
671: TreeTableNode node = this;
672: while ((node = node.parent) != null)
673: dist += node.rowNr;
674: return dist;
675: }
676: }
|