public ProjectTreePanel(
      EntityCollection entityCollection,
      SymbolGraphic symbolGraphic,
      String panelName,
      KinDiagramPanel kinDiagramPanel,
      GraphPanel graphPanel,
      MessageDialogHandler dialogHandler,
      ArbilDataNodeLoader dataNodeLoader) {
    super(new BorderLayout());
    this.setName(panelName);
    this.entityCollection = entityCollection;
    this.symbolGraphic = symbolGraphic;
    this.panelName = panelName;
    this.kinDiagramPanel = kinDiagramPanel;
    this.graphPanel = graphPanel;
    this.dataNodeLoader = dataNodeLoader;
    this.dialogHandler = dialogHandler;
    this.rootNode = new ProjectNode(entityCollection, panelName);
    kinTree = new KinTree(kinDiagramPanel, graphPanel, rootNode);
    kinTree.setBackground(this.getBackground());
    this.add(new JScrollPane(kinTree), BorderLayout.CENTER);
    progressBar = new JProgressBar();
    ActionListener actionListener =
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if ("<".equals(e.getActionCommand())) {
              currentPage--;
            } else if (">".equals(e.getActionCommand())) {
              currentPage++;
            }
            showPage();
          }
        };
    final JButton previousButton = new JButton("<");
    final JButton nextButton = new JButton(">");
    currentPageLabel = new JLabel("", JLabel.CENTER);

    previousButton.setActionCommand("<");
    nextButton.setActionCommand(">");

    previousButton.addActionListener(actionListener);
    nextButton.addActionListener(actionListener);

    final Dimension preferredSize = previousButton.getPreferredSize();
    final Dimension buttonDimension = new Dimension(preferredSize.height, preferredSize.height);
    previousButton.setPreferredSize(buttonDimension);
    nextButton.setPreferredSize(buttonDimension);

    pagePanel = new JPanel(new BorderLayout());
    pagePanel.add(previousButton, BorderLayout.LINE_START);
    pagePanel.add(currentPageLabel, BorderLayout.CENTER);
    pagePanel.add(nextButton, BorderLayout.LINE_END);
  }
 private void showPage() {
   if (treeNodesArray != null) {
     int pageCount = treeNodesArray.size() / maxNodesPerPage;
     if (currentPage < 0) {
       currentPage = 0;
     }
     if (currentPage > pageCount) {
       currentPage = pageCount;
     }
     final int startNode = currentPage * maxNodesPerPage;
     int endNode = startNode + maxNodesPerPage;
     if (endNode > treeNodesArray.size()) {
       endNode = treeNodesArray.size();
     }
     currentPageLabel.setText((currentPage + 1) + " of " + (pageCount + 1));
     rootNode.setChildNodes(
         treeNodesArray.subList(startNode, endNode).toArray(new ArbilNode[] {}));
     kinTree.requestResort();
   }
   progressBar.setVisible(false);
   ProjectTreePanel.this.remove(progressBar);
   ProjectTreePanel.this.add(pagePanel, BorderLayout.PAGE_END);
   this.revalidate();
 }
 @Override
 public void setTransferHandler(TransferHandler newHandler) {
   kinTree.setTransferHandler(newHandler);
   kinTree.setDragEnabled(true);
 }
 public void loadProjectTree() {
   ProjectTreePanel.this.remove(pagePanel);
   ProjectTreePanel.this.add(progressBar, BorderLayout.PAGE_END);
   progressBar.setVisible(true);
   progressBar.setIndeterminate(true);
   this.revalidate();
   kinTree.requestResort();
   new Thread() {
     @Override
     public void run() {
       boolean projectQueryRunning = ATOMIC_BOOLEAN.getAndSet(true);
       synchronized (lockObject) {
         final ArrayList<KinTreeNode> tempTreeNodesArray = new ArrayList<KinTreeNode>();
         if (!projectQueryRunning && updateRequired) {
           try {
             EntityData[] projectEntities =
                 entityCollection.getEntityByEndPoint(
                     DataTypes.RelationType.ancestor, graphPanel.getIndexParameters());
             for (EntityData entityData : projectEntities) {
               boolean isHorizontalEndPoint = true;
               // this check is for end points that have a sibling or spouse who are not an end
               // point, but it is removed because it is not possible to browse to a spouse or
               // sibling in a directional branch
               //                    for (EntityRelation entityRelation :
               // entityData.getAllRelations()) {
               //                        if (entityRelation.getAlterNode() == null) {
               //                            // if the alter node has not been loaded then it must
               // not be an end point
               //                            if (entityRelation.getRelationType() ==
               // DataTypes.RelationType.union || entityRelation.getRelationType() ==
               // DataTypes.RelationType.sibling) {
               //                                isHorizontalEndPoint = false;
               //                                break;
               //                            }
               //                        }
               //                    }
               if (isHorizontalEndPoint) {
                 // todo: add cache and update (on change) of the tree nodes
                 tempTreeNodesArray.add(
                     new KinTreeNode(
                         symbolGraphic,
                         entityData.getUniqueIdentifier(),
                         entityData,
                         graphPanel.dataStoreSvg,
                         graphPanel.getIndexParameters(),
                         dialogHandler,
                         entityCollection,
                         dataNodeLoader));
               }
             }
             Collections.sort(tempTreeNodesArray);
             updateRequired = false;
           } catch (EntityServiceException exception) {
             dialogHandler.addMessageDialogToQueue(exception.getMessage(), "Get Project Entities");
           }
         }
         treeNodesArray = tempTreeNodesArray;
         SwingUtilities.invokeLater(
             new Runnable() {
               public void run() {
                 showPage();
               }
             });
         ATOMIC_BOOLEAN.set(false);
       }
     }
   }.start();
 }