Desktop tool for browsing account info from EVE-Online
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ListableConfigDialog.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * Copyright (c) 2009 Chris Smith
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package uk.co.md87.evetool.ui.dialogs.listableconfig;
  23. import java.awt.Dialog.ModalityType;
  24. import java.awt.Dimension;
  25. import java.awt.Window;
  26. import java.awt.event.ActionEvent;
  27. import java.awt.event.ActionListener;
  28. import java.awt.event.ItemEvent;
  29. import java.awt.event.ItemListener;
  30. import java.awt.event.KeyEvent;
  31. import java.awt.event.KeyListener;
  32. import java.util.ArrayList;
  33. import java.util.Collections;
  34. import java.util.HashMap;
  35. import java.util.List;
  36. import java.util.Map;
  37. import java.util.Set;
  38. import javax.swing.BorderFactory;
  39. import javax.swing.JButton;
  40. import javax.swing.JComboBox;
  41. import javax.swing.JComponent;
  42. import javax.swing.JDialog;
  43. import javax.swing.JLabel;
  44. import javax.swing.JMenuItem;
  45. import javax.swing.JPanel;
  46. import javax.swing.JPopupMenu;
  47. import javax.swing.JSeparator;
  48. import javax.swing.JTextField;
  49. import net.miginfocom.swing.MigLayout;
  50. import uk.co.md87.evetool.ui.components.ListablePanel;
  51. import uk.co.md87.evetool.ui.listable.Listable;
  52. import uk.co.md87.evetool.ui.listable.ListableConfig;
  53. import uk.co.md87.evetool.ui.listable.ListableConfig.BasicConfigElement;
  54. import uk.co.md87.evetool.ui.listable.ListableConfig.CompoundConfigElement;
  55. import uk.co.md87.evetool.ui.listable.ListableConfig.ConfigElement;
  56. import uk.co.md87.evetool.ui.listable.ListableConfig.LiteralConfigElement;
  57. import uk.co.md87.evetool.ui.listable.ListableParser;
  58. /**
  59. *
  60. * TODO: Document ListableConfigDialog
  61. * @author chris
  62. */
  63. public class ListableConfigDialog extends JDialog implements ItemListener, KeyListener {
  64. /**
  65. * A version number for this class. It should be changed whenever the class
  66. * structure is changed (or anything else that would prevent serialized
  67. * objects being unserialized with the new class).
  68. */
  69. private static final long serialVersionUID = 10;
  70. private final ListableConfig config;
  71. private final Listable sample;
  72. private final ListableParser parser;
  73. private final Set<String> retrievables;
  74. private final Map<String, List<JComponent>> components
  75. = new HashMap<String, List<JComponent>>();
  76. private final JPanel configPanel, previewPanel;
  77. private final ListablePanel panel;
  78. public ListableConfigDialog(final Window owner, final ListableConfig config,
  79. final Listable sample) {
  80. super(owner, "Display Configuration", ModalityType.APPLICATION_MODAL);
  81. setLayout(new MigLayout("wrap 1, fill", "[fill]", "[|fill|fill]"));
  82. this.config = config;
  83. this.sample = sample;
  84. this.parser = new ListableParser(sample.getClass());
  85. this.retrievables = parser.getRetrievableNames();
  86. this.configPanel = new JPanel(new MigLayout("fill", "[fill]"));
  87. this.previewPanel = new JPanel(new MigLayout("fill", "[fill]", "[fill]"));
  88. configPanel.setBorder(BorderFactory.createTitledBorder("Information"));
  89. previewPanel.setBorder(BorderFactory.createTitledBorder("Preview"));
  90. this.panel = new ListablePanel(sample, parser, config);
  91. previewPanel.add(panel);
  92. add(configPanel);
  93. add(previewPanel);
  94. initConfigPanel();
  95. layoutConfigPanel();
  96. pack();
  97. setLocationRelativeTo(owner);
  98. setResizable(false);
  99. }
  100. protected void initConfigPanel() {
  101. components.put("tl", getComponents(config.topLeft));
  102. components.put("tr", getComponents(config.topRight));
  103. components.put("bl", getComponents(config.bottomLeft));
  104. components.put("br", getComponents(config.bottomRight));
  105. components.put("+group", getComponents(config.group));
  106. for (int i = 0; i < config.sortOrder.length; i++) {
  107. components.put("+sort_" + i, getComponents(config.sortOrder[i]));
  108. }
  109. }
  110. protected void layoutConfigPanel() {
  111. configPanel.removeAll();
  112. JButton addButton;
  113. final List<String> keyset = new ArrayList<String>(components.keySet());
  114. Collections.sort(keyset);
  115. for (int i = 0; i < keyset.size(); i++) {
  116. final String key = keyset.get(i);
  117. addButton = new JButton("+");
  118. addButton.addActionListener(new ButtonActionListener(key));
  119. addButton.setMaximumSize(new Dimension(35, 100));
  120. configPanel.add(new JLabel(getText(key), JLabel.RIGHT));
  121. addComponents(key);
  122. configPanel.add(addButton, "span, al right");
  123. if (key.length() > 2 && i < keyset.size() - 1
  124. && !keyset.get(i + 1).startsWith(key.substring(0, 4))) {
  125. configPanel.add(new JSeparator(),
  126. "gaptop 10, gapbottom 10, newline, span, growx");
  127. }
  128. }
  129. configPanel.revalidate();
  130. pack();
  131. }
  132. protected String getText(final String key) {
  133. if (key.equals("+group")) {
  134. return "Group by:";
  135. }
  136. if (key.startsWith("+sort")) {
  137. return key.equals("+sort_0") ? "Sort by:" : "... then:";
  138. }
  139. final StringBuilder builder = new StringBuilder();
  140. builder.append(key.startsWith("t") ? "Top" : "Bottom");
  141. builder.append(' ');
  142. builder.append(key.endsWith("r") ? "right" : "left");
  143. builder.append(':');
  144. return builder.toString();
  145. }
  146. protected void addComponents(final String location) {
  147. for (JComponent component : components.get(location)) {
  148. configPanel.add(component, "growy, width 100!");
  149. }
  150. }
  151. protected List<JComponent> getComponents(final ConfigElement element) {
  152. final List<JComponent> res = new ArrayList<JComponent>();
  153. if (element instanceof LiteralConfigElement) {
  154. final JTextField tf = new JTextField(((LiteralConfigElement) element).getText());
  155. tf.addKeyListener(this);
  156. res.add(tf);
  157. } else if (element instanceof BasicConfigElement) {
  158. final JComboBox box = new JComboBox(retrievables.toArray());
  159. box.addItemListener(this);
  160. box.setSelectedItem(((BasicConfigElement) element).getName());
  161. res.add(box);
  162. } else {
  163. for (ConfigElement subElement : ((CompoundConfigElement) element).getElements()) {
  164. res.addAll(getComponents(subElement));
  165. }
  166. }
  167. return res;
  168. }
  169. protected void rebuildConfig() {
  170. for (String loc : new String[]{"tl", "tr", "bl", "br"}) {
  171. final List<ConfigElement> elements = new ArrayList<ConfigElement>();
  172. if (!components.containsKey(loc)) {
  173. continue;
  174. }
  175. for (JComponent component : components.get(loc)) {
  176. if (component instanceof JTextField) {
  177. elements.add(new LiteralConfigElement(((JTextField) component).getText()));
  178. } else if (component instanceof JComboBox) {
  179. elements.add(new BasicConfigElement((String)
  180. ((JComboBox) component).getSelectedItem()));
  181. }
  182. }
  183. final ConfigElement res = new CompoundConfigElement(
  184. elements.toArray(new ConfigElement[0]));
  185. if (loc.equals("tl")) {
  186. config.topLeft = res;
  187. } else if (loc.equals("tr")) {
  188. config.topRight = res;
  189. } else if (loc.equals("br")) {
  190. config.bottomRight = res;
  191. } else if (loc.equals("bl")) {
  192. config.bottomLeft = res;
  193. }
  194. }
  195. }
  196. /** {@inheritDoc} */
  197. @Override
  198. public void itemStateChanged(final ItemEvent e) {
  199. rebuildConfig();
  200. panel.listableUpdated(sample);
  201. }
  202. /** {@inheritDoc} */
  203. @Override
  204. public void keyTyped(final KeyEvent e) {
  205. // Do nothing
  206. }
  207. /** {@inheritDoc} */
  208. @Override
  209. public void keyPressed(final KeyEvent e) {
  210. // Do nothing
  211. }
  212. /** {@inheritDoc} */
  213. @Override
  214. public void keyReleased(final KeyEvent e) {
  215. rebuildConfig();
  216. panel.listableUpdated(sample);
  217. }
  218. private class ButtonActionListener implements ActionListener {
  219. private final String location;
  220. public ButtonActionListener(final String location) {
  221. this.location = location;
  222. }
  223. public void actionPerformed(final ActionEvent e) {
  224. final JPopupMenu menu = new JPopupMenu();
  225. JMenuItem mi = new JMenuItem("New string");
  226. mi.addActionListener(new MenuActionListener(location, true));
  227. menu.add(mi);
  228. mi = new JMenuItem("New variable");
  229. mi.addActionListener(new MenuActionListener(location, false));
  230. menu.add(mi);
  231. menu.show((JComponent) e.getSource(), 0,
  232. ((JComponent) e.getSource()).getHeight());
  233. }
  234. }
  235. private class MenuActionListener implements ActionListener {
  236. private final String location;
  237. private final boolean isString;
  238. public MenuActionListener(final String location, final boolean isString) {
  239. this.location = location;
  240. this.isString = isString;
  241. }
  242. public void actionPerformed(final ActionEvent e) {
  243. if (isString) {
  244. final JTextField tf = new JTextField();
  245. tf.addKeyListener(ListableConfigDialog.this);
  246. components.get(location).add(tf);
  247. } else {
  248. final JComboBox box = new JComboBox(retrievables.toArray());
  249. box.addItemListener(ListableConfigDialog.this);
  250. components.get(location).add(box);
  251. }
  252. layoutConfigPanel();
  253. rebuildConfig();
  254. panel.listableUpdated(sample);
  255. }
  256. }
  257. }