/plugins/CommonControls/tags/v_0_9_4/common/gui/PopupList.java

# · Java · 459 lines · 257 code · 43 blank · 159 comment · 27 complexity · 569f7e7d56952752363bbc152ecfd10d MD5 · raw file

  1. /*
  2. * PopupList.java
  3. * Copyright (C) 2002 Calvin Yu
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. package common.gui;
  20. // {{{ Imports
  21. import java.awt.BorderLayout;
  22. import java.awt.Component;
  23. import java.awt.Dimension;
  24. import java.awt.Point;
  25. import java.awt.event.*;
  26. import java.util.ArrayList;
  27. import java.util.Iterator;
  28. import java.util.LinkedList;
  29. import java.util.List;
  30. import javax.swing.*;
  31. import org.gjt.sp.jedit.jEdit;
  32. import org.gjt.sp.jedit.View;
  33. import org.gjt.sp.jedit.gui.DefaultInputHandler;
  34. import org.gjt.sp.util.Log;
  35. // }}}
  36. /**
  37. * A popup control for displaying a arbitrary list of items.
  38. */
  39. public class PopupList
  40. implements FocusListener, WindowListener
  41. {
  42. static final private int DEFAULT_VISIBLE_ROW_COUNT = 5;
  43. private boolean requestTextAreaFocusOnCancel;
  44. private JPanel panel;
  45. private JList list;
  46. private ListModel model;
  47. private List listeners;
  48. private JWindow window;
  49. /**
  50. * Create a new <code>PopupList</code>.
  51. */
  52. public PopupList()
  53. {
  54. this(DEFAULT_VISIBLE_ROW_COUNT);
  55. requestTextAreaFocusOnCancel = true;
  56. }
  57. /**
  58. * Create a new <code>PopupList</code>.
  59. */
  60. public PopupList(int visibleRowCount)
  61. {
  62. panel = new JPanel(new BorderLayout(0, 0));
  63. model = new ListModel();
  64. list = new JList(model);
  65. list.addFocusListener(this);
  66. list.setVisibleRowCount(visibleRowCount);
  67. list.setCellRenderer(new ListItemListCellRenderer());
  68. panel.add(new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
  69. JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
  70. listeners = new LinkedList();
  71. list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "selectItem");
  72. list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "selectItem");
  73. list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel");
  74. list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "nextItem");
  75. list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "previousItem");
  76. list.getActionMap().put("selectItem", new SelectItemAction());
  77. list.getActionMap().put("cancel", new CancelAction());
  78. list.getActionMap().put("nextItem", new SelectNextItemAction());
  79. list.getActionMap().put("previousItem", new SelectPreviousItemAction());
  80. }
  81. /**
  82. * Enable key stroke cycling.
  83. *
  84. * @deprecated As of CC 0.9.0, this method does nothing.
  85. */
  86. public void enableKeyStrokeCycling(String anActionName)
  87. {
  88. }
  89. /**
  90. * Disable key stroke cycling.
  91. *
  92. * @deprecated As of CC 0.9.0, this method does nothing.
  93. */
  94. public void disableKeyStrokeCycling()
  95. {
  96. }
  97. /**
  98. * Set the items to show.
  99. */
  100. public void setItems(List theItems)
  101. {
  102. model.setItems(theItems);
  103. }
  104. /**
  105. * Returns the selected item.
  106. */
  107. public ListItem getSelectedItem()
  108. {
  109. return (ListItem) list.getSelectedValue();
  110. }
  111. /**
  112. * Returns the selected actual item. This is equivalent of calling
  113. * <code>getSelectedItem().getActualItem()</code>.
  114. */
  115. public Object getSelectedActualItem()
  116. {
  117. return getSelectedItem().getActualItem();
  118. }
  119. /**
  120. * Sets the selected actual item.
  121. */
  122. public void setSelectedActualItem(Object actualItem)
  123. {
  124. int itemIndex = model.indexOfActualItem(actualItem);
  125. list.setSelectedIndex(itemIndex);
  126. }
  127. /**
  128. * Set whether focus should go to the main text area if this popup is
  129. * cancelled. The default is <code>false</code>.
  130. */
  131. public void setRequestTextAreaFocusOnCancel(boolean b)
  132. {
  133. requestTextAreaFocusOnCancel = b;
  134. }
  135. /**
  136. * Show this popup in a window.
  137. */
  138. public void show(View view)
  139. {
  140. if (window != null) {
  141. Log.log(Log.WARNING, this, "Popup already shown");
  142. return;
  143. }
  144. window = new JWindow(view);
  145. window.setContentPane(panel);
  146. window.pack();
  147. Point viewLoc = view.getLocation();
  148. Dimension viewSize = view.getSize();
  149. Dimension popupSize = window.getSize();
  150. Point popLoc = new Point(viewLoc.x + ((viewSize.width - popupSize.width) / 2),
  151. viewLoc.y + ((viewSize.height - popupSize.height) / 2));
  152. window.addWindowListener(this);
  153. window.setLocation(popLoc);
  154. window.setVisible(true);
  155. list.requestFocus();
  156. }
  157. /**
  158. * Cancel the popup.
  159. */
  160. public void cancel()
  161. {
  162. if (window != null) {
  163. window.dispose();
  164. if (requestTextAreaFocusOnCancel) {
  165. View view = (View) window.getOwner();
  166. view.getEditPane().getTextArea().requestFocus();
  167. }
  168. window = null;
  169. }
  170. }
  171. /**
  172. * Add an <code>java.awt.event.ActionListener</code>.
  173. */
  174. public void addActionListener(ActionListener listener)
  175. {
  176. listeners.add(listener);
  177. }
  178. /**
  179. * Show this popup.
  180. *
  181. * @param view The view requesting the popup.
  182. * @param items The list of {@link ListItem}s to show.
  183. * @param selectedActualItem The {@link ListItem#getActualItem()} that is selected.
  184. * @param listener The <code>java.awt.event.ActionListener</code> to invoke
  185. * when a selection is made.
  186. */
  187. static public PopupList show(View view, List items,
  188. Object selectedActualItem,
  189. ActionListener listener)
  190. {
  191. PopupList popupList = new PopupList();
  192. popupList.addActionListener(listener);
  193. popupList.setItems(items);
  194. popupList.setSelectedActualItem(selectedActualItem);
  195. popupList.show(view);
  196. return popupList;
  197. }
  198. /**
  199. * Show this popup.
  200. *
  201. * @param view The view requesting the popup.
  202. * @param items The list of {@link ListItem}s to show.
  203. * @param listener The <code>java.awt.event.ActionListener</code> to invoke
  204. * when a selection is made.
  205. */
  206. static public PopupList show(View view, List items, ActionListener listener)
  207. {
  208. return show(view, items, null, listener);
  209. }
  210. // {{{ FocusListener Methods
  211. public final void focusGained(FocusEvent evt) {}
  212. public final void focusLost(FocusEvent evt) {
  213. cancel();
  214. }
  215. // }}}
  216. // {{{ WindowListener Methods
  217. /**
  218. * Handle a window closing event.
  219. */
  220. public final void windowClosing(WindowEvent evt) {}
  221. /**
  222. * Handle a window closed event.
  223. */
  224. public final void windowClosed(WindowEvent evt) {}
  225. /**
  226. * Handle a window opened event.
  227. */
  228. public final void windowOpened(WindowEvent evt) {}
  229. /**
  230. * Handle a window activated event.
  231. */
  232. public final void windowActivated(WindowEvent evt) {}
  233. /**
  234. * Handle a window deactivated event.
  235. */
  236. public final void windowDeactivated(WindowEvent evt) {
  237. cancel();
  238. }
  239. /**
  240. * Handle a window iconified event.
  241. */
  242. public final void windowIconified(WindowEvent evt) {}
  243. /**
  244. * Handle a window deiconified event.
  245. */
  246. public final void windowDeiconified(WindowEvent evt)
  247. {
  248. cancel();
  249. }
  250. // }}}
  251. /**
  252. * Fire an action event.
  253. */
  254. private void fireActionPerformed()
  255. {
  256. ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null);
  257. for (Iterator i = listeners.iterator(); i.hasNext();) {
  258. ((ActionListener) i.next()).actionPerformed(evt);
  259. }
  260. }
  261. /**
  262. * A list model implementation.
  263. */
  264. private class ListModel extends AbstractListModel
  265. {
  266. private List items;
  267. /**
  268. * Create a new <code>ListModel</code>.
  269. */
  270. public ListModel()
  271. {
  272. items = new ArrayList();
  273. }
  274. /**
  275. * Set the items.
  276. */
  277. public void setItems(List theItems)
  278. {
  279. if (!items.isEmpty()) {
  280. int lastIdx = items.size() - 1;
  281. items.clear();
  282. fireIntervalRemoved(this, 0, lastIdx);
  283. }
  284. items = theItems;
  285. if (!items.isEmpty()) {
  286. fireIntervalAdded(this, 0, items.size() - 1);
  287. }
  288. }
  289. /**
  290. * Returns the index of the first {@link ListItem} that contains the given
  291. * actual item.
  292. */
  293. public int indexOfActualItem(Object actualItem)
  294. {
  295. int i = 0;
  296. for (Iterator iter = items.iterator(); iter.hasNext();) {
  297. ListItem each = (ListItem) iter.next();
  298. if (actualItem == null && each.getActualItem() == null) {
  299. return i;
  300. } else if (actualItem != null && actualItem.equals(each.getActualItem())) {
  301. return i;
  302. }
  303. i++;
  304. }
  305. return -1;
  306. }
  307. /**
  308. * Returns the element at the given index.
  309. */
  310. public Object getElementAt(int index)
  311. {
  312. return items.get(index);
  313. }
  314. /**
  315. * Returns the number of items.
  316. */
  317. public int getSize()
  318. {
  319. return items.size();
  320. }
  321. }
  322. /**
  323. * A list cell renderer for {@link ListItem}s.
  324. */
  325. private class ListItemListCellRenderer extends DefaultListCellRenderer
  326. {
  327. /**
  328. * Returns the renderer component.
  329. */
  330. public Component getListCellRendererComponent(JList list, Object value,
  331. int index,
  332. boolean isSelected,
  333. boolean cellHasFocus)
  334. {
  335. ListItem item = (ListItem) value;
  336. value = item.getLabel();
  337. Component c = super.getListCellRendererComponent(list, value, index,
  338. isSelected,
  339. cellHasFocus);
  340. setIcon(item.getIcon());
  341. return c;
  342. }
  343. }
  344. /**
  345. * An action to cancel the popup.
  346. */
  347. private class CancelAction extends AbstractAction
  348. {
  349. /**
  350. * Cancel the popup.
  351. */
  352. public void actionPerformed(ActionEvent evt)
  353. {
  354. cancel();
  355. }
  356. }
  357. /**
  358. * An action selecting the current item.
  359. */
  360. private class SelectItemAction extends AbstractAction
  361. {
  362. /**
  363. * Select the current item.
  364. */
  365. public void actionPerformed(ActionEvent evt)
  366. {
  367. window.dispose();
  368. window = null;
  369. fireActionPerformed();
  370. }
  371. }
  372. /**
  373. * Select the previous item
  374. */
  375. private class SelectPreviousItemAction extends AbstractAction
  376. {
  377. /**
  378. * Select the previous item.
  379. */
  380. public void actionPerformed(ActionEvent evt)
  381. {
  382. int idx = list.getSelectedIndex();
  383. if (idx < 0) {
  384. idx = 0;
  385. } else if (idx == 0) {
  386. idx = model.getSize() - 1;
  387. } else {
  388. idx--;
  389. }
  390. list.setSelectedIndex(idx);
  391. list.ensureIndexIsVisible(idx);
  392. }
  393. }
  394. /**
  395. * Select the next item
  396. */
  397. private class SelectNextItemAction extends AbstractAction
  398. {
  399. /**
  400. * Select the next item.
  401. */
  402. public void actionPerformed(ActionEvent evt)
  403. {
  404. int idx = list.getSelectedIndex();
  405. if (idx < 0) {
  406. idx = 0;
  407. } else if (idx == (model.getSize() - 1)) {
  408. idx = 0;
  409. } else {
  410. idx++;
  411. }
  412. list.setSelectedIndex(idx);
  413. list.ensureIndexIsVisible(idx);
  414. }
  415. }
  416. }