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.

ChannelFrame.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * Copyright (c) 2006-2007 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.ui.swing;
  23. import com.dmdirc.Channel;
  24. import com.dmdirc.Main;
  25. import com.dmdirc.commandparser.commands.ChannelCommand;
  26. import com.dmdirc.commandparser.parsers.ChannelCommandParser;
  27. import com.dmdirc.commandparser.commands.Command;
  28. import com.dmdirc.commandparser.parsers.CommandParser;
  29. import com.dmdirc.commandparser.commands.ServerCommand;
  30. import com.dmdirc.parser.ChannelClientInfo;
  31. import com.dmdirc.ui.input.InputHandler;
  32. import com.dmdirc.ui.interfaces.ChannelWindow;
  33. import com.dmdirc.ui.swing.components.InputFrame;
  34. import com.dmdirc.ui.swing.dialogs.channelsetting.ChannelSettingsDialog;
  35. import static com.dmdirc.ui.swing.UIUtilities.SMALL_BORDER;
  36. import java.awt.BorderLayout;
  37. import java.awt.Color;
  38. import java.awt.Dimension;
  39. import java.awt.Point;
  40. import java.awt.event.ActionEvent;
  41. import java.awt.event.ActionListener;
  42. import java.awt.event.MouseEvent;
  43. import java.awt.event.MouseListener;
  44. import java.util.List;
  45. import javax.swing.JList;
  46. import javax.swing.JMenuItem;
  47. import javax.swing.JPanel;
  48. import javax.swing.JScrollPane;
  49. import javax.swing.JSplitPane;
  50. import javax.swing.ListSelectionModel;
  51. import javax.swing.SwingUtilities;
  52. import javax.swing.plaf.basic.BasicSplitPaneDivider;
  53. import javax.swing.plaf.basic.BasicSplitPaneUI;
  54. /**
  55. * The channel frame is the GUI component that represents a channel to the user.
  56. */
  57. public final class ChannelFrame extends InputFrame implements MouseListener,
  58. ActionListener, ChannelWindow {
  59. /**
  60. * A version number for this class. It should be changed whenever the class
  61. * structure is changed (or anything else that would prevent serialized
  62. * objects being unserialized with the new class).
  63. */
  64. private static final long serialVersionUID = 10;
  65. /** The nick list model used for this channel's nickname list. */
  66. private NicklistListModel nicklistModel;
  67. /** This channel's command parser. */
  68. private final ChannelCommandParser commandParser;
  69. /** Nick list. */
  70. private JList nickList;
  71. /** split pane. */
  72. private JSplitPane splitPane;
  73. /** popup menu item. */
  74. private JMenuItem settingsMI;
  75. /** The channel object that owns this frame. */
  76. private final Channel parent;
  77. /**
  78. * Creates a new instance of ChannelFrame. Sets up callbacks and handlers,
  79. * and default options for the form.
  80. * @param owner The Channel object that owns this frame
  81. */
  82. public ChannelFrame(final Channel owner) {
  83. super(owner);
  84. parent = owner;
  85. initComponents();
  86. nickList.setBackground(getConfigManager().getOptionColour("ui", "nicklistbackgroundcolour",
  87. getConfigManager().getOptionColour("ui", "backgroundcolour", Color.WHITE)));
  88. nickList.setForeground(getConfigManager().getOptionColour("ui", "nicklistforegroundcolour",
  89. getConfigManager().getOptionColour("ui", "foregroundcolour", Color.BLACK)));
  90. getConfigManager().addChangeListener("ui", "nicklistforegroundcolour", this);
  91. getConfigManager().addChangeListener("ui", "nicklistbackgroundcolour", this);
  92. getConfigManager().addChangeListener("nicklist", "altBackgroundColour", this);
  93. commandParser = new ChannelCommandParser(((Channel) getContainer()).
  94. getServer(), (Channel) getContainer());
  95. setInputHandler(new InputHandler(getInputField(), commandParser, this));
  96. }
  97. /**
  98. * Retrieves the command Parser for this command window.
  99. * @return This window's command Parser
  100. */
  101. public CommandParser getCommandParser() {
  102. return commandParser;
  103. }
  104. /** {@inheritDoc} */
  105. public void updateNames(final List<ChannelClientInfo> clients) {
  106. SwingUtilities.invokeLater(new Runnable() {
  107. public void run() {
  108. nicklistModel.replace(clients);
  109. }
  110. });
  111. }
  112. /** {@inheritDoc} */
  113. public void updateNames() {
  114. nicklistModel.sort();
  115. }
  116. /** {@inheritDoc} */
  117. public void addName(final ChannelClientInfo client) {
  118. SwingUtilities.invokeLater(new Runnable() {
  119. public void run() {
  120. nicklistModel.add(client);
  121. }
  122. });
  123. }
  124. /** {@inheritDoc} */
  125. public void removeName(final ChannelClientInfo client) {
  126. SwingUtilities.invokeLater(new Runnable() {
  127. public void run() {
  128. nicklistModel.remove(client);
  129. }
  130. });
  131. }
  132. /**
  133. * Retrieves this channel frame's nicklist component.
  134. * @return This channel's nicklist
  135. */
  136. public JList getNickList() {
  137. return nickList;
  138. }
  139. /**
  140. * Initialises the compoents in this frame.
  141. */
  142. private void initComponents() {
  143. settingsMI = new JMenuItem("Settings");
  144. settingsMI.addActionListener(this);
  145. getPopup().addSeparator();
  146. getPopup().add(settingsMI);
  147. final JPanel panel = new JPanel(new BorderLayout());
  148. splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
  149. final JScrollPane nickScrollPane = new JScrollPane();
  150. nickList = new JList();
  151. nickList.setCellRenderer(new NicklistRenderer(parent.getConfigManager()));
  152. nickList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  153. nickList.addMouseListener(this);
  154. splitPane.setBorder(null);
  155. final BasicSplitPaneDivider divider =
  156. ((BasicSplitPaneUI) splitPane.getUI()).getDivider();
  157. if (divider != null) {
  158. divider.setBorder(null);
  159. }
  160. nicklistModel = new NicklistListModel();
  161. nickList.setModel(nicklistModel);
  162. nickScrollPane.setViewportView(nickList);
  163. nickScrollPane.setMinimumSize(new Dimension(150, 10));
  164. getTextPane().setPreferredSize(new Dimension(((MainFrame) Main.getUI().
  165. getMainWindow()).getWidth(), 10));
  166. panel.add(getSearchBar(), BorderLayout.PAGE_START);
  167. panel.add(inputPanel, BorderLayout.PAGE_END);
  168. getContentPane().setLayout(new BorderLayout(SMALL_BORDER, SMALL_BORDER));
  169. getContentPane().add(splitPane, BorderLayout.CENTER);
  170. getContentPane().add(panel, BorderLayout.PAGE_END);
  171. splitPane.setLeftComponent(getTextPane());
  172. splitPane.setRightComponent(nickScrollPane);
  173. splitPane.setDividerLocation((double) 1);
  174. splitPane.setResizeWeight(1);
  175. splitPane.setDividerSize(SMALL_BORDER);
  176. splitPane.setContinuousLayout(true);
  177. pack();
  178. }
  179. /**
  180. * {@inheritDoc}.
  181. */
  182. public void actionPerformed(final ActionEvent actionEvent) {
  183. super.actionPerformed(actionEvent);
  184. if (commands.containsKey(actionEvent.getActionCommand())) {
  185. final Command command = commands.get(actionEvent.getActionCommand());
  186. for (Object nickname : nickList.getSelectedValues()) {
  187. if (command instanceof ChannelCommand) {
  188. ((ChannelCommand) commands.get(actionEvent.getActionCommand())).
  189. execute(this, getContainer().getServer(),
  190. (Channel) this.getContainer(), false,
  191. ((ChannelClientInfo) nickname).getNickname());
  192. } else if (command instanceof ServerCommand) {
  193. ((ServerCommand) commands.get(actionEvent.getActionCommand())).
  194. execute(this, getContainer().getServer(), false,
  195. ((ChannelClientInfo) nickname).getNickname());
  196. }
  197. }
  198. }
  199. if (actionEvent.getSource() == settingsMI) {
  200. ChannelSettingsDialog.getChannelSettingDialog((Channel) getContainer()).setVisible(true);
  201. }
  202. }
  203. /**
  204. * Returns the splitpane.
  205. * @return nicklist JSplitPane
  206. */
  207. public JSplitPane getSplitPane() {
  208. return splitPane;
  209. }
  210. /**
  211. * Checks for url's, channels and nicknames. {@inheritDoc}
  212. */
  213. public void mouseClicked(final MouseEvent mouseEvent) {
  214. processMouseEvent(mouseEvent);
  215. super.mouseClicked(mouseEvent);
  216. }
  217. /**
  218. * Not needed for this class. {@inheritDoc}
  219. */
  220. public void mousePressed(final MouseEvent mouseEvent) {
  221. processMouseEvent(mouseEvent);
  222. super.mousePressed(mouseEvent);
  223. }
  224. /**
  225. * Not needed for this class. {@inheritDoc}
  226. */
  227. public void mouseReleased(final MouseEvent mouseEvent) {
  228. processMouseEvent(mouseEvent);
  229. super.mouseReleased(mouseEvent);
  230. }
  231. /**
  232. * Processes every mouse button event to check for a popup trigger.
  233. *
  234. * @param e mouse event
  235. */
  236. public void processMouseEvent(final MouseEvent e) {
  237. if (e.getSource() == nickList && nickList.getMousePosition() != null) {
  238. boolean showMenu = false;
  239. showMenu = checkShowNicklistMenu();
  240. if (!showMenu) {
  241. showMenu = selectNickUnderCursor();
  242. }
  243. if (showMenu) {
  244. if (e.isPopupTrigger()) {
  245. final Point point = getMousePosition();
  246. popuplateNicklistPopup();
  247. nicklistPopup.show(this, (int) point.getX(), (int) point.getY());
  248. }
  249. } else {
  250. nickList.clearSelection();
  251. }
  252. }
  253. super.processMouseEvent(e);
  254. }
  255. /**
  256. *
  257. * Checks whether to show the nicklist menu.
  258. *
  259. * @return whether to show the nicklist menu
  260. */
  261. private boolean checkShowNicklistMenu() {
  262. boolean showMenu = false;
  263. for (int i = 0; i < nickList.getModel().getSize(); i++) {
  264. if (nickList.getCellBounds(i, i) != null
  265. && nickList.getMousePosition() != null
  266. && nickList.getCellBounds(i, i).contains(nickList.getMousePosition())
  267. && nickList.isSelectedIndex(i)) {
  268. showMenu = true;
  269. break;
  270. }
  271. }
  272. return showMenu;
  273. }
  274. /**
  275. * Selects the nick underneath the mouse.
  276. *
  277. * @return true if an item was selected
  278. */
  279. private boolean selectNickUnderCursor() {
  280. boolean suceeded = false;
  281. if (nickList.getMousePosition() != null) {
  282. for (int i = 0; i < nickList.getModel().getSize(); i++) {
  283. if (nickList.getCellBounds(i, i) != null
  284. && nickList.getMousePosition() != null
  285. && nickList.getCellBounds(i, i).contains(nickList.getMousePosition())) {
  286. nickList.setSelectedIndex(i);
  287. suceeded = true;
  288. break;
  289. }
  290. }
  291. }
  292. return suceeded;
  293. }
  294. /** {@inheritDoc} */
  295. @Override
  296. public void configChanged(final String domain, final String key,
  297. final String oldValue, final String newValue) {
  298. super.configChanged(domain, key, oldValue, newValue);
  299. if ("ui".equals(domain)) {
  300. if ("nicklistbackgroundcolour".equals(key) || "backgroundcolour".equals(key)) {
  301. nickList.setBackground(getConfigManager().getOptionColour("ui", "nicklistbackgroundcolour",
  302. getConfigManager().getOptionColour("ui", "backgroundcolour", Color.WHITE)));
  303. } else if ("nicklistforegroundcolour".equals(key) || "foregroundcolour".equals(key)) {
  304. nickList.setForeground(getConfigManager().getOptionColour("ui", "nicklistforegroundcolour",
  305. getConfigManager().getOptionColour("ui", "foregroundcolour", Color.BLACK)));
  306. }
  307. } else if ("nicklist".equals(domain) && "altBackgroundColour".equals(key)) {
  308. nickList.repaint();
  309. }
  310. }
  311. }