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 10KB

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