PageRenderTime 49ms CodeModel.GetById 36ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/org/sylfra/idea/plugins/revu/ui/forms/AbstractListUpdatableForm.java

https://github.com/syllant/idea-plugin-revu
Java | 381 lines | 290 code | 63 blank | 28 comment | 29 complexity | e9b4559beb67f334b82ade8f4ee203af MD5 | raw file
  1package org.sylfra.idea.plugins.revu.ui.forms;
  2
  3import com.intellij.openapi.Disposable;
  4import com.intellij.openapi.actionSystem.*;
  5import com.intellij.openapi.options.Configurable;
  6import com.intellij.openapi.options.ConfigurationException;
  7import com.intellij.openapi.project.Project;
  8import org.jetbrains.annotations.Nls;
  9import org.jetbrains.annotations.NonNls;
 10import org.jetbrains.annotations.NotNull;
 11import org.jetbrains.annotations.Nullable;
 12import org.sylfra.idea.plugins.revu.RevuBundle;
 13import org.sylfra.idea.plugins.revu.model.IRevuUniqueNameHolderEntity;
 14
 15import javax.swing.*;
 16import java.awt.*;
 17import java.util.*;
 18import java.util.List;
 19
 20/**
 21 * Used to interface settings inside Settings panel
 22 *
 23 * @author <a href="mailto:syllant@gmail.com">Sylvain FRANCOIS</a>
 24 * @version $Id$
 25 */
 26public abstract class AbstractListUpdatableForm<E extends IRevuUniqueNameHolderEntity<E>,
 27  F extends AbstractUpdatableForm<E>> implements Configurable, Disposable
 28{
 29  protected final Project project;
 30  protected JComponent contentPane;
 31  protected JComponent toolBar;
 32  protected RevuEntityJList<E> list;
 33  protected JLabel lbMessageWholePane;
 34  protected JLabel lbMessageMainPane;
 35  protected F mainForm;
 36  protected final IdentityHashMap<E, E> originalItemsMap;
 37  private JPanel mainPane;
 38
 39  public AbstractListUpdatableForm(@NotNull Project project)
 40  {
 41    this.project = project;
 42    originalItemsMap = new IdentityHashMap<E,E>();
 43
 44    setupUI();
 45    configureUI();
 46  }
 47
 48  public void dispose()
 49  {
 50    mainForm.dispose();
 51  }
 52
 53  protected void setupUI()
 54  {
 55    mainForm = createMainForm();
 56
 57    // List
 58    JPanel pnList = new JPanel(new BorderLayout());
 59    pnList.setMinimumSize(new Dimension(50, 0));
 60    pnList.setMinimumSize(new Dimension(150, 0));
 61
 62    list = new RevuEntityJList<E>(createListSelectedEntityDataKey(), createListAllEntitiesDataKeys());
 63
 64    // Toolbar
 65    ActionToolbar actionToolbar = ActionManager.getInstance()
 66      .createActionToolbar(ActionPlaces.UNKNOWN, createActionGroup(), true);
 67    actionToolbar.setTargetComponent(list);
 68    toolBar = actionToolbar.getComponent();
 69
 70    pnList.add(new JScrollPane(list), BorderLayout.CENTER);
 71    pnList.add(toolBar, BorderLayout.NORTH);
 72
 73    contentPane = new JPanel();
 74    contentPane.setLayout(new CardLayout(0, 0));
 75
 76    JSplitPane splitPane = new JSplitPane();
 77    contentPane.add(splitPane, "pane");
 78
 79    lbMessageMainPane = new JLabel();
 80    lbMessageMainPane.setHorizontalAlignment(0);
 81    lbMessageMainPane.setHorizontalTextPosition(SwingConstants.CENTER);
 82
 83    mainPane = new JPanel(new CardLayout(0, 0));
 84    mainPane.add(mainForm.getContentPane(), "pane");
 85    mainPane.add(lbMessageMainPane, "message");
 86
 87    splitPane.setLeftComponent(pnList);
 88    splitPane.setRightComponent(mainPane);
 89//    splitPane.setDividerLocation(150);
 90//    splitPane.setResizeWeight(0);
 91
 92    lbMessageWholePane = new JLabel();
 93    lbMessageWholePane.setHorizontalAlignment(0);
 94    lbMessageWholePane.setHorizontalTextPosition(SwingConstants.CENTER);
 95    contentPane.add(lbMessageWholePane, "message");
 96  }
 97
 98  protected void configureUI()
 99  {
100    list.setCellRenderer(new DefaultListCellRenderer()
101    {
102      @SuppressWarnings({"unchecked"})
103      @Override
104      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
105        boolean cellHasFocus)
106      {
107        E entity = (E) value;
108        value = entity.getName();
109
110        Component result = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
111        AbstractListUpdatableForm.this.customizeListCellRendererComponent((JLabel) result, list, entity, index,
112          isSelected, cellHasFocus);
113
114        return result;
115      }
116    });
117    list.setSelectionModel(new DefaultListSelectionModel()
118    {
119      @Override
120      public void setSelectionInterval(int index0, int index1)
121      {
122        if (updateFormData())
123        {
124          super.setSelectionInterval(index1, index1);
125          updateFormUI();
126        }
127      }
128    });
129  }
130
131  public void addItem(E item)
132  {
133    DefaultListModel model = (DefaultListModel) list.getModel();
134
135    // Put item according to sort
136    int index = 0;
137    //noinspection unchecked
138    while ((index < model.getSize()) && (((E) model.getElementAt(index)).compareTo(item) < 0))
139    {
140      index++;
141    }
142
143    model.add(index, item);
144
145    list.clearSelection();
146    list.setSelectedValue(item, true);
147  }
148
149  protected void showWholeMessage(boolean visible)
150  {
151    showMessage(contentPane, visible);
152  }
153
154  protected void showMainMessage(boolean visible)
155  {
156    showMessage(mainPane, visible);
157  }
158
159  private void showMessage(JComponent pane, boolean visible)
160  {
161    // pane may be null when closing form
162    if (pane == null)
163    {
164      return;
165    }
166
167    CardLayout cardLayout = (CardLayout) pane.getLayout();
168    if (visible)
169    {
170      cardLayout.show(pane, "message");
171    }
172    else
173    {
174      cardLayout.show(pane, "pane");
175    }
176  }
177
178  @SuppressWarnings({"unchecked"})
179  private boolean updateFormData()
180  {
181    E current = (E) list.getSelectedValue();
182    return (current == null) || mainForm.updateData(current);
183  }
184
185  @SuppressWarnings({"unchecked"})
186  private void updateFormUI()
187  {
188    E current = (E) list.getSelectedValue();
189    if (current != null)
190    {
191      showMainMessage(false);
192      mainForm.updateUI(null, current, true);
193    }
194    else
195    {
196      String msgKey = getMessageKeyWhenNoSelection();
197      if (msgKey != null)
198      {
199        lbMessageMainPane.setText(RevuBundle.message(msgKey));
200      }
201
202      showMainMessage(true);
203    }
204  }
205
206  /**
207   * {@inheritDoc}
208   */
209  @SuppressWarnings({"unchecked"})
210  public boolean isModified()
211  {
212    if (lbMessageWholePane.isVisible())
213    {
214      return false;
215    }
216
217    // Item count
218    int itemCount = list.getModel().getSize();
219    if (itemCount != originalItemsMap.size())
220    {
221      return true;
222    }
223
224    // Current edited item
225    E selectedValue = (E) list.getSelectedValue();
226    if (selectedValue == null)
227    {
228      return false;
229    }
230    
231    if (mainForm.isModified(selectedValue))
232    {
233      return true;
234    }
235
236    // Other lists
237    for (int i = 0; i < itemCount; i++)
238    {
239      E item = (E) list.getModel().getElementAt(i);
240      if (!item.equals(originalItemsMap.get(item)))
241      {
242        return true;
243      }
244    }
245
246    return false;
247  }
248
249  /**
250   * {@inheritDoc}
251   */
252  public final void apply() throws ConfigurationException
253  {
254    if (!updateFormData())
255    {
256      throw new ConfigurationException(
257        RevuBundle.message("general.form.hasErrors.text"), RevuBundle.message("general.plugin.title"));
258    }
259
260    int itemCount = list.getModel().getSize();
261    Map<E, E> items = new HashMap<E, E>(itemCount);
262    for (int i=0; i < itemCount; i++)
263    {
264      //noinspection unchecked
265      E item = (E) list.getModel().getElementAt(i);
266      items.put(item, originalItemsMap.get(item));
267    }
268
269    apply(items);
270  }
271
272  /**
273   * {@inheritDoc}
274   */
275  public void reset()
276  {
277    updateFormUI();
278
279    DefaultListModel listModel = new DefaultListModel();
280
281    originalItemsMap.clear();
282
283    List<E> originalItems = getOriginalItems();
284    for (E item : originalItems)
285    {
286      // List stores shallow clones so changes may be properly canceled
287      E clone = item.clone();
288      originalItemsMap.put(clone, item);
289      listModel.addElement(clone);
290    }
291
292    list.setModel(listModel);
293    if (list.getModel().getSize() > 0)
294    {
295      list.setSelectedIndex(0);
296    }
297  }
298
299  protected E retrieveCloneItem(@NotNull E item)
300  {
301    for (Map.Entry<E, E> entry : originalItemsMap.entrySet())
302    {
303      if (entry.getValue().equals(item))
304      {
305        return entry.getKey();
306      }
307    }
308
309    return null;
310  }
311
312  public void selectItem(@NotNull E item)
313  {
314    list.setSelectedValue(item, true);
315  }
316
317  public JComponent getContentPane()
318  {
319    return contentPane;
320  }
321
322  @SuppressWarnings({"UnusedDeclaration"})
323  protected void customizeListCellRendererComponent(JLabel renderer, JList list, E entity, int index, boolean selected,
324    boolean cellHasFocus)
325  {
326  }
327
328  @Nullable
329  @Nls
330  protected String getMessageKeyWhenNoSelection()
331  {
332    return null;
333  }
334
335  protected abstract void apply(Map<E, E> items) throws ConfigurationException;
336
337  protected abstract F createMainForm();
338
339  protected abstract ActionGroup createActionGroup();
340
341  protected abstract DataKey createListSelectedEntityDataKey();
342
343  protected abstract DataKey createListAllEntitiesDataKeys();
344
345  @NotNull
346  protected abstract List<E> getOriginalItems();
347
348  protected static class RevuEntityJList<E extends IRevuUniqueNameHolderEntity<E>> extends JList implements DataProvider
349  {
350    private final DataKey listSelectedEntityDataKey;
351    private final DataKey listAllEntitiesDataKeys;
352
353    public RevuEntityJList(DataKey listSelectedEntityDataKey, DataKey listAllEntitiesDataKeys)
354    {
355      this.listSelectedEntityDataKey = listSelectedEntityDataKey;
356      this.listAllEntitiesDataKeys = listAllEntitiesDataKeys;
357    }
358
359    public Object getData(@NonNls String dataId)
360    {
361      if (listSelectedEntityDataKey.getName().equals(dataId))
362      {
363        return getSelectedValue();
364      }
365
366      if (listAllEntitiesDataKeys.getName().equals(dataId))
367      {
368        List<E> items = new ArrayList<E>(getModel().getSize());
369        for (int i=0; i<getModel().getSize(); i++)
370        {
371          //noinspection unchecked
372          items.add((E) getModel().getElementAt(i));
373        }
374
375        return items;
376      }
377
378      return null;
379    }
380  }
381}