private synchronized void dispose() {
   timer.stop();
   UIManager.removePropertyChangeListener(this);
   synchronized (AnimationController.class) {
     AppContext.getAppContext().put(ANIMATION_CONTROLLER_KEY, null);
   }
 }
 public synchronized void actionPerformed(ActionEvent e) {
   java.util.List<JComponent> componentsToRemove = null;
   java.util.List<Part> partsToRemove = null;
   for (JComponent component : animationStateMap.keySet()) {
     component.repaint();
     if (partsToRemove != null) {
       partsToRemove.clear();
     }
     Map<Part, AnimationState> map = animationStateMap.get(component);
     if (!component.isShowing() || map == null || map.size() == 0) {
       if (componentsToRemove == null) {
         componentsToRemove = new ArrayList<JComponent>();
       }
       componentsToRemove.add(component);
       continue;
     }
     for (Part part : map.keySet()) {
       if (map.get(part).isDone()) {
         if (partsToRemove == null) {
           partsToRemove = new ArrayList<Part>();
         }
         partsToRemove.add(part);
       }
     }
     if (partsToRemove != null) {
       if (partsToRemove.size() == map.size()) {
         // animation is done for the component
         if (componentsToRemove == null) {
           componentsToRemove = new ArrayList<JComponent>();
         }
         componentsToRemove.add(component);
       } else {
         for (Part part : partsToRemove) {
           map.remove(part);
         }
       }
     }
   }
   if (componentsToRemove != null) {
     for (JComponent component : componentsToRemove) {
       animationStateMap.remove(component);
     }
   }
   if (animationStateMap.size() == 0) {
     timer.stop();
   }
 }