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.

NickList.java 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * Copyright (c) 2006-2011 Chris Smith, Shane Mc Cormack, Gregory Holmes
  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 com.dmdirc.addons.ui_swing.components;
  23. import com.dmdirc.Channel;
  24. import com.dmdirc.addons.ui_swing.components.frames.ChannelFrame;
  25. import com.dmdirc.addons.ui_swing.components.renderers.NicklistRenderer;
  26. import com.dmdirc.addons.ui_swing.textpane.ClickType;
  27. import com.dmdirc.addons.ui_swing.textpane.ClickTypeValue;
  28. import com.dmdirc.config.ConfigManager;
  29. import com.dmdirc.interfaces.ConfigChangeListener;
  30. import com.dmdirc.interfaces.NicklistListener;
  31. import com.dmdirc.parser.interfaces.ChannelClientInfo;
  32. import java.awt.Dimension;
  33. import java.awt.Point;
  34. import java.awt.event.MouseEvent;
  35. import java.awt.event.MouseListener;
  36. import java.util.Collection;
  37. import javax.swing.JList;
  38. import javax.swing.JScrollPane;
  39. import javax.swing.ListSelectionModel;
  40. import javax.swing.SwingUtilities;
  41. /**
  42. * Nicklist class.
  43. */
  44. public class NickList extends JScrollPane implements ConfigChangeListener,
  45. MouseListener, NicklistListener {
  46. /**
  47. * A version number for this class. It should be changed whenever the class
  48. * structure is changed (or anything else that would prevent serialized
  49. * objects being unserialized with the new class).
  50. */
  51. private static final long serialVersionUID = 10;
  52. /** Nick list. */
  53. private final JList nickList;
  54. /** Parent frame. */
  55. private final ChannelFrame frame;
  56. /** Config. */
  57. private final ConfigManager config;
  58. /** Nick list model. */
  59. private final NicklistListModel nicklistModel;
  60. /**
  61. * Creates a nicklist.
  62. *
  63. * @param frame Frame
  64. * @param config Config
  65. */
  66. public NickList(final ChannelFrame frame, final ConfigManager config) {
  67. super();
  68. this.frame = frame;
  69. this.config = config;
  70. nickList = new JList();
  71. nickList.setBackground(config.getOptionColour(
  72. "ui", "nicklistbackgroundcolour",
  73. "ui", "backgroundcolour"));
  74. nickList.setForeground(config.getOptionColour(
  75. "ui", "nicklistforegroundcolour",
  76. "ui", "foregroundcolour"));
  77. config.addChangeListener("ui", "nicklistforegroundcolour", this);
  78. config.addChangeListener("ui", "foregroundcolour", this);
  79. config.addChangeListener("ui", "nicklistbackgroundcolour", this);
  80. config.addChangeListener("ui", "backgroundcolour", this);
  81. config.addChangeListener("ui", "nickListAltBackgroundColour", this);
  82. nickList.setCellRenderer(new NicklistRenderer(config, nickList));
  83. nickList.setSelectionMode(
  84. ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  85. nickList.addMouseListener(this);
  86. nicklistModel = new NicklistListModel(config);
  87. nickList.setModel(nicklistModel);
  88. setViewportView(nickList);
  89. final int splitPanePosition = config.getOptionInt("ui",
  90. "channelSplitPanePosition");
  91. setPreferredSize(new Dimension(splitPanePosition, 0));
  92. setMinimumSize(new Dimension(75, 0));
  93. ((Channel) frame.getContainer()).addNicklistListener(this);
  94. clientListUpdated(((Channel) frame.getContainer()).getChannelInfo()
  95. .getChannelClients());
  96. }
  97. /**
  98. * {@inheritDoc}
  99. *
  100. * @param e Mouse event
  101. */
  102. @Override
  103. public void mouseClicked(final MouseEvent e) {
  104. processMouseEvent(e);
  105. }
  106. /**
  107. * {@inheritDoc}
  108. *
  109. * @param e Mouse event
  110. */
  111. @Override
  112. public void mousePressed(final MouseEvent e) {
  113. processMouseEvent(e);
  114. }
  115. /**
  116. * {@inheritDoc}
  117. *
  118. * @param e Mouse event
  119. */
  120. @Override
  121. public void mouseReleased(final MouseEvent e) {
  122. processMouseEvent(e);
  123. }
  124. /**
  125. * {@inheritDoc}
  126. *
  127. * @param e Mouse event
  128. */
  129. @Override
  130. public void mouseEntered(final MouseEvent e) {
  131. //Ignore
  132. }
  133. /**
  134. * {@inheritDoc}
  135. *
  136. * @param e Mouse event
  137. */
  138. @Override
  139. public void mouseExited(final MouseEvent e) {
  140. //Ignore
  141. }
  142. /**
  143. * Processes every mouse button event to check for a popup trigger.
  144. *
  145. * @param e mouse event
  146. */
  147. @Override
  148. public void processMouseEvent(final MouseEvent e) {
  149. if (!e.isPopupTrigger()
  150. || e.getSource() != nickList
  151. || nickList.getMousePosition() == null) {
  152. return;
  153. }
  154. if (checkCursorInSelectedCell() || selectNickUnderCursor()) {
  155. final Object[] values = nickList.getSelectedValues();
  156. final StringBuilder builder = new StringBuilder();
  157. for (Object value : values) {
  158. if (builder.length() > 0) {
  159. builder.append("\n");
  160. }
  161. builder.append(((ChannelClientInfo) value).getClient()
  162. .getNickname());
  163. }
  164. frame.showPopupMenu(new ClickTypeValue(ClickType.NICKNAME,
  165. builder.toString()), new Point(e.getXOnScreen(),
  166. e.getYOnScreen()));
  167. } else {
  168. nickList.clearSelection();
  169. }
  170. super.processMouseEvent(e);
  171. }
  172. /**
  173. * Checks whether the mouse cursor is currently over a cell in the nicklist
  174. * which has been previously selected.
  175. *
  176. * @return True if the cursor is over a selected cell, false otherwise
  177. */
  178. private boolean checkCursorInSelectedCell() {
  179. boolean showMenu = false;
  180. final Point mousePos = nickList.getMousePosition();
  181. if (mousePos != null) {
  182. for (int i = 0; i < nickList.getModel().getSize(); i++) {
  183. if (nickList.getCellBounds(i, i) != null && nickList.
  184. getCellBounds(i, i).
  185. contains(mousePos) && nickList.isSelectedIndex(i)) {
  186. showMenu = true;
  187. break;
  188. }
  189. }
  190. }
  191. return showMenu;
  192. }
  193. /**
  194. * If the mouse cursor is over a nicklist cell, sets that cell to be
  195. * selected and returns true. If the mouse is not over any cell, the
  196. * selection is unchanged and the method returns false.
  197. *
  198. * @return True if an item was selected
  199. */
  200. private boolean selectNickUnderCursor() {
  201. boolean suceeded = false;
  202. final Point mousePos = nickList.getMousePosition();
  203. if (mousePos != null) {
  204. for (int i = 0; i < nickList.getModel().getSize(); i++) {
  205. if (nickList.getCellBounds(i, i) != null && nickList.
  206. getCellBounds(i, i).
  207. contains(mousePos)) {
  208. nickList.setSelectedIndex(i);
  209. suceeded = true;
  210. break;
  211. }
  212. }
  213. }
  214. return suceeded;
  215. }
  216. /** {@inheritDoc} */
  217. @Override
  218. public void configChanged(final String domain, final String key) {
  219. if ("nickListAltBackgroundColour".equals(key)
  220. || "nicklistbackgroundcolour".equals(key)
  221. || "backgroundcolour".equals(key)
  222. || "nicklistforegroundcolour".equals(key)
  223. || "foregroundcolour".equals(key)) {
  224. nickList.setBackground(config.getOptionColour(
  225. "ui", "nicklistbackgroundcolour",
  226. "ui", "backgroundcolour"));
  227. nickList.setForeground(config.getOptionColour(
  228. "ui", "nicklistforegroundcolour",
  229. "ui", "foregroundcolour"));
  230. nickList.repaint();
  231. }
  232. nickList.setSelectionMode(
  233. ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  234. }
  235. /** {@inheritDoc} */
  236. @Override
  237. public void clientListUpdated(final Collection<ChannelClientInfo> clients) {
  238. SwingUtilities.invokeLater(new Runnable() {
  239. /** {@inheritDoc} */
  240. @Override
  241. public void run() {
  242. nicklistModel.replace(clients);
  243. }
  244. });
  245. }
  246. /** {@inheritDoc} */
  247. @Override
  248. public void clientListUpdated() {
  249. SwingUtilities.invokeLater(new Runnable() {
  250. /** {@inheritDoc} */
  251. @Override
  252. public void run() {
  253. nicklistModel.sort();
  254. repaint();
  255. }
  256. });
  257. }
  258. /** {@inheritDoc} */
  259. @Override
  260. public void clientAdded(final ChannelClientInfo client) {
  261. SwingUtilities.invokeLater(new Runnable() {
  262. /** {@inheritDoc} */
  263. @Override
  264. public void run() {
  265. nicklistModel.add(client);
  266. }
  267. });
  268. }
  269. /** {@inheritDoc} */
  270. @Override
  271. public void clientRemoved(final ChannelClientInfo client) {
  272. SwingUtilities.invokeLater(new Runnable() {
  273. /** {@inheritDoc} */
  274. @Override
  275. public void run() {
  276. nicklistModel.remove(client);
  277. }
  278. });
  279. }
  280. }