// TODO: THIS IS RATHER UGLY, too many params but better than what was here before
  public void registerTab(
      PetriNet net,
      PetriNetTab tab,
      Observer historyObserver,
      UndoableEditListener undoListener,
      PropertyChangeListener zoomListener) {
    AnimationHistoryImpl animationHistory = new AnimationHistoryImpl();
    animationHistory.addObserver(historyObserver);
    GUIAnimator animator = new GUIAnimator(new PetriNetAnimator(net), animationHistory, this);

    CopyPasteManager copyPasteManager = new CopyPasteManager(undoListener, tab, net, this);

    ZoomController zoomController = new ZoomController(100);
    tab.addZoomListener(zoomController);
    PetriNetController petriNetController =
        new PetriNetController(net, undoListener, animator, copyPasteManager, zoomController, tab);
    netControllers.put(tab, petriNetController);
    tab.updatePreferredSize();

    PropertyChangeListener changeListener =
        new PetriNetChangeListener(applicationModel, tab, petriNetController);
    net.addPropertyChangeListener(changeListener);

    setActiveTab(tab);
    initialiseNet(net, changeListener);
  }
  /**
   * This is a little hacky, I'm not sure how to make this better when it's so late If a better
   * implementation is clear please re-write
   *
   * <p>This method invokes the change listener which will create the view objects on the petri net
   * tab
   *
   * @param propertyChangeListener
   */
  private void initialiseNet(PetriNet net, PropertyChangeListener propertyChangeListener) {
    for (Token token : net.getTokens()) {
      PropertyChangeEvent changeEvent =
          new PropertyChangeEvent(net, PetriNet.NEW_TOKEN_CHANGE_MESSAGE, null, token);
      propertyChangeListener.propertyChange(changeEvent);
    }

    for (Place place : net.getPlaces()) {
      PropertyChangeEvent changeEvent =
          new PropertyChangeEvent(net, PetriNet.NEW_PLACE_CHANGE_MESSAGE, null, place);
      propertyChangeListener.propertyChange(changeEvent);
    }

    for (Transition transition : net.getTransitions()) {
      PropertyChangeEvent changeEvent =
          new PropertyChangeEvent(net, PetriNet.NEW_TRANSITION_CHANGE_MESSAGE, null, transition);
      propertyChangeListener.propertyChange(changeEvent);
    }

    for (Arc<? extends Connectable, ? extends Connectable> arc : net.getArcs()) {
      PropertyChangeEvent changeEvent =
          new PropertyChangeEvent(net, PetriNet.NEW_ARC_CHANGE_MESSAGE, null, arc);
      propertyChangeListener.propertyChange(changeEvent);
    }

    for (Annotation annotation : net.getAnnotations()) {
      PropertyChangeEvent changeEvent =
          new PropertyChangeEvent(net, PetriNet.NEW_ANNOTATION_CHANGE_MESSAGE, null, annotation);
      propertyChangeListener.propertyChange(changeEvent);
    }

    for (RateParameter rateParameter : net.getRateParameters()) {
      PropertyChangeEvent changeEvent =
          new PropertyChangeEvent(
              net, PetriNet.NEW_RATE_PARAMETER_CHANGE_MESSAGE, null, rateParameter);
      propertyChangeListener.propertyChange(changeEvent);
    }
  }