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