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

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