package com.intellij.uiDesigner.palette;

import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.ArrayList;

/**
 * @author yole
 */
public class PaletteWindow extends JPanel implements Scrollable {
  private Project myProject;
  private Palette myPalette;
  private ArrayList<PaletteGroup> myGroups = new ArrayList<PaletteGroup>();

  public PaletteWindow(Project project) {
    myProject = project;
    setLayout(new PaletteLayoutManager());
    myPalette = Palette.getInstance(project);

    for (GroupItem groupItem : myPalette.getGroups()) {
      PaletteGroup group = new PaletteGroup(groupItem);
      myGroups.add(group);
      add(group);
      PaletteComponentList componentList = new PaletteComponentList(groupItem);
      add(componentList);
      group.setComponentList(componentList);
      componentList.addListSelectionListener(new MyListSelectionListener());
    }
  }

  public Dimension getPreferredScrollableViewportSize() {
    return getPreferredSize();
  }

  public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
    return 20;
  }

  public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
    return 100;
  }

  public boolean getScrollableTracksViewportWidth() {
    return true;
  }

  public boolean getScrollableTracksViewportHeight() {
    return false;
  }

  public void clearActiveItem() {
    for(PaletteGroup group: myGroups) {
      group.getComponentList().clearSelection();
    }
  }

  @Nullable public ComponentItem getActiveItem() {
    for(PaletteGroup group: myGroups) {
      if (group.isSelected() && group.getComponentList().getSelectedValue() != null) {
        return (ComponentItem) group.getComponentList().getSelectedValue();
      }
    }
    return null;
  }

  private class PaletteLayoutManager implements LayoutManager {

    public void addLayoutComponent(String name, Component comp) {
    }

    public void layoutContainer(Container parent) {
      int width = getWidth();

      int height = 0;
      for(PaletteGroup group: myGroups) {
        group.setLocation(0, height);
        group.setSize(width, group.getPreferredSize().height);
        height += group.getPreferredSize().height;
        if (group.isSelected()) {
          PaletteComponentList componentList = group.getComponentList();
          componentList.setSize(width, componentList.getPreferredSize().height);
          componentList.setLocation(0, height);
          height += componentList.getHeight();
        }
      }
    }

    public Dimension minimumLayoutSize(Container parent) {
      return new Dimension(0, 0);
    }

    public Dimension preferredLayoutSize(Container parent) {
      int height = 0;
      int width = getWidth();
      for(PaletteGroup group: myGroups) {
        height += group.getHeight();
        if (group.isSelected()) {
          height += group.getComponentList().getPreferredHeight(width);
        }
      }
      return new Dimension(10 /* not used - tracks viewports width*/, height);
    }

    public void removeLayoutComponent(Component comp) {
    }
  }

  private class MyListSelectionListener implements ListSelectionListener {
    public void valueChanged(ListSelectionEvent e) {
      PaletteComponentList sourceList = (PaletteComponentList) e.getSource();
      for(int i=e.getFirstIndex(); i <= e.getLastIndex(); i++) {
        if (sourceList.isSelectedIndex(i)) {
          // selection is being added
          for(PaletteGroup group: myGroups) {
            if (group.getComponentList() != sourceList) {
              group.getComponentList().clearSelection();
            }
          }
          break;
        }
      }
    }
  }
}

@@ -668,16 +668,350 @@
 oject);%0A
+    myPalette.addListener(new Palette.Listener() %7B%0A      public void groupsChanged(Palette palette) %7B%0A        refreshPalette();%0A      %7D%0A    %7D);%0A%0A    refreshPalette();%0A  %7D%0A%0A  private void refreshPalette() %7B%0A    for(PaletteGroup group: myGroups) %7B%0A      remove(group);%0A      remove(group.getComponentList());%0A    %7D%0A    myGroups.clear();
 %0A    for
@@ -1390,24 +1390,42 @@
 r());%0A    %7D%0A
+    revalidate();%0A
   %7D%0A%0A  publi

update palette on change (IDEADEV-4075)