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.

Channel.java 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  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;
  23. import com.dmdirc.actions.ActionManager;
  24. import com.dmdirc.actions.CoreActionType;
  25. import com.dmdirc.commandparser.CommandManager;
  26. import com.dmdirc.identities.ConfigManager;
  27. import com.dmdirc.logger.ErrorLevel;
  28. import com.dmdirc.logger.Logger;
  29. import com.dmdirc.parser.ChannelClientInfo;
  30. import com.dmdirc.parser.ChannelInfo;
  31. import com.dmdirc.parser.ClientInfo;
  32. import com.dmdirc.parser.IRCParser;
  33. import com.dmdirc.parser.callbacks.CallbackManager;
  34. import com.dmdirc.parser.callbacks.CallbackNotFound;
  35. import com.dmdirc.parser.callbacks.interfaces.IAwayStateOther;
  36. import com.dmdirc.parser.callbacks.interfaces.IChannelAction;
  37. import com.dmdirc.parser.callbacks.interfaces.IChannelCTCP;
  38. import com.dmdirc.parser.callbacks.interfaces.IChannelGotNames;
  39. import com.dmdirc.parser.callbacks.interfaces.IChannelJoin;
  40. import com.dmdirc.parser.callbacks.interfaces.IChannelKick;
  41. import com.dmdirc.parser.callbacks.interfaces.IChannelMessage;
  42. import com.dmdirc.parser.callbacks.interfaces.IChannelModeChanged;
  43. import com.dmdirc.parser.callbacks.interfaces.IChannelNickChanged;
  44. import com.dmdirc.parser.callbacks.interfaces.IChannelPart;
  45. import com.dmdirc.parser.callbacks.interfaces.IChannelQuit;
  46. import com.dmdirc.parser.callbacks.interfaces.IChannelTopic;
  47. import com.dmdirc.parser.callbacks.interfaces.IChannelUserModeChanged;
  48. import com.dmdirc.ui.ChannelFrame;
  49. import com.dmdirc.ui.InputWindow;
  50. import com.dmdirc.ui.MainFrame;
  51. import com.dmdirc.ui.input.TabCompleter;
  52. import com.dmdirc.ui.messages.ColourManager;
  53. import com.dmdirc.ui.messages.Formatter;
  54. import com.dmdirc.ui.messages.Styliser;
  55. import java.awt.Color;
  56. import java.lang.reflect.InvocationTargetException;
  57. import java.net.URL;
  58. import java.util.ArrayList;
  59. import java.util.HashMap;
  60. import java.util.Map;
  61. import javax.swing.ImageIcon;
  62. import javax.swing.SwingUtilities;
  63. /**
  64. * The Channel class represents the client's view of the channel. It handles
  65. * callbacks for channel events from the parser, maintains the corresponding
  66. * ChannelFrame, and handles user input to a ChannelFrame.
  67. *
  68. * @author chris
  69. */
  70. public final class Channel extends FrameContainer implements IChannelMessage,
  71. IChannelGotNames, IChannelTopic, IChannelJoin, IChannelPart,
  72. IChannelKick, IChannelQuit, IChannelAction, IChannelNickChanged,
  73. IChannelModeChanged, IChannelUserModeChanged, IChannelCTCP,
  74. IAwayStateOther {
  75. /**
  76. * The callbacks that should be registered for channel instances.
  77. */
  78. private static final String[] CALLBACKS = {
  79. "OnChannelMessage", "OnChannelGotNames", "OnChannelTopic",
  80. "OnChannelJoin", "OnChannelPart", "OnChannelKick", "OnChannelQuit",
  81. "OnChannelAction", "OnChannelNickChanged", "OnChannelModeChanged",
  82. "OnChannelUserModeChanged", "OnChannelCTCP",
  83. };
  84. /** The parser's pChannel class. */
  85. private ChannelInfo channelInfo;
  86. /** The server this channel is on. */
  87. private Server server;
  88. /** The ChannelFrame used for this channel. */
  89. private ChannelFrame frame;
  90. /** The tabcompleter used for this channel. */
  91. private final TabCompleter tabCompleter;
  92. /** The config manager for this channel. */
  93. private final ConfigManager configManager;
  94. /** Whether we're in this channel or not. */
  95. private boolean onChannel;
  96. /**
  97. * Creates a new instance of Channel.
  98. * @param newServer The server object that this channel belongs to
  99. * @param newChannelInfo The parser's channel object that corresponds to
  100. * this channel
  101. */
  102. public Channel(final Server newServer, final ChannelInfo newChannelInfo) {
  103. super();
  104. channelInfo = newChannelInfo;
  105. server = newServer;
  106. configManager = new ConfigManager(server.getIrcd(), server.getNetwork(),
  107. server.getName(), channelInfo.getName());
  108. final ClassLoader cldr = this.getClass().getClassLoader();
  109. final URL imageURL = cldr.getResource("com/dmdirc/res/channel.png");
  110. imageIcon = new ImageIcon(imageURL);
  111. tabCompleter = new TabCompleter(server.getTabCompleter());
  112. tabCompleter.addEntries(CommandManager.getChannelCommandNames());
  113. try {
  114. SwingUtilities.invokeAndWait(new Runnable() {
  115. public void run() {
  116. frame = new ChannelFrame(Channel.this);
  117. MainFrame.getMainFrame().addChild(frame);
  118. frame.addInternalFrameListener(Channel.this);
  119. frame.setFrameIcon(imageIcon);
  120. frame.getInputHandler().setTabCompleter(tabCompleter);
  121. }
  122. });
  123. } catch (InvocationTargetException ex) {
  124. Logger.error(ErrorLevel.FATAL, "Unable to load channel", ex.getCause());
  125. } catch (InterruptedException ex) {
  126. Logger.error(ErrorLevel.FATAL, "Unable to load channel", ex);
  127. }
  128. registerCallbacks();
  129. ActionManager.processEvent(CoreActionType.CHANNEL_OPENED, null, this);
  130. updateTitle();
  131. selfJoin();
  132. }
  133. /**
  134. * Registers callbacks with the parser for this channel.
  135. */
  136. private void registerCallbacks() {
  137. try {
  138. final CallbackManager callbackManager = server.getParser().getCallbackManager();
  139. final String channel = channelInfo.getName();
  140. for (String callback : CALLBACKS) {
  141. callbackManager.addCallback(callback, this, channel);
  142. }
  143. } catch (CallbackNotFound ex) {
  144. Logger.error(ErrorLevel.FATAL, "Unable to load channel", ex);
  145. }
  146. }
  147. /**
  148. * Shows this channel's frame.
  149. */
  150. public void show() {
  151. frame.open();
  152. }
  153. /** {@inheritDoc} */
  154. @Override
  155. public ConfigManager getConfigManager() {
  156. return configManager;
  157. }
  158. /**
  159. * Sends the specified line as a message to the channel that this object
  160. * represents.
  161. * @param line The message to send
  162. */
  163. public void sendLine(final String line) {
  164. final ClientInfo me = server.getParser().getMyself();
  165. final String modes = getModes(channelInfo.getUser(me));
  166. final String[] details = getDetails(channelInfo.getUser(me));
  167. final int maxLineLength = server.getParser().getMaxLength("PRIVMSG", getChannelInfo().getName());
  168. if (maxLineLength >= line.length()) {
  169. final StringBuffer buff = new StringBuffer("channelSelfMessage");
  170. ActionManager.processEvent(CoreActionType.CHANNEL_SELF_MESSAGE, buff,
  171. this, channelInfo.getUser(me), line);
  172. frame.addLine(buff, modes, details[0], details[1], details[2],
  173. line, channelInfo);
  174. channelInfo.sendMessage(line);
  175. } else {
  176. sendLine(line.substring(0, maxLineLength));
  177. sendLine(line.substring(maxLineLength));
  178. }
  179. }
  180. /**
  181. * Sends the specified string as an action (CTCP) to the channel that this object
  182. * represents.
  183. * @param action The action to send
  184. */
  185. public void sendAction(final String action) {
  186. final ClientInfo me = server.getParser().getMyself();
  187. final String modes = channelInfo.getUser(me).getImportantModePrefix();
  188. if (server.getParser().getMaxLength("PRIVMSG", getChannelInfo().getName()) <= action.length()) {
  189. frame.addLine("actionTooLong", action.length());
  190. } else {
  191. final StringBuffer buff = new StringBuffer("channelSelfAction");
  192. ActionManager.processEvent(CoreActionType.CHANNEL_SELF_ACTION, buff,
  193. this, channelInfo.getUser(me), action);
  194. frame.addLine(buff, modes, me.getNickname(), me.getIdent(),
  195. me.getHost(), action, channelInfo);
  196. channelInfo.sendAction(action);
  197. }
  198. }
  199. /**
  200. * Returns the server object that this channel belongs to.
  201. * @return The server object
  202. */
  203. public Server getServer() {
  204. return server;
  205. }
  206. /**
  207. * Returns the parser's ChannelInfo object that this object is associated with.
  208. * @return The ChannelInfo object associated with this object
  209. */
  210. public ChannelInfo getChannelInfo() {
  211. return channelInfo;
  212. }
  213. /**
  214. * Sets this object's ChannelInfo reference to the one supplied. This only needs
  215. * to be done if the channel window (and hence this channel object) has stayed
  216. * open while the user has been out of the channel.
  217. * @param newChannelInfo The new ChannelInfo object
  218. */
  219. public void setChannelInfo(final ChannelInfo newChannelInfo) {
  220. channelInfo = newChannelInfo;
  221. registerCallbacks();
  222. }
  223. /**
  224. * Returns the internal frame belonging to this object.
  225. * @return This object's internal frame
  226. */
  227. public InputWindow getFrame() {
  228. return frame;
  229. }
  230. /**
  231. * Returns the tab completer for this channel.
  232. * @return This channel's tab completer
  233. */
  234. public TabCompleter getTabCompleter() {
  235. return tabCompleter;
  236. }
  237. /**
  238. * Called when we join this channel. Just needs to output a message.
  239. */
  240. public void selfJoin() {
  241. onChannel = true;
  242. final ClientInfo me = server.getParser().getMyself();
  243. frame.addLine("channelSelfJoin", "", me.getNickname(), me.getIdent(),
  244. me.getHost(), channelInfo.getName());
  245. }
  246. /**
  247. * Updates the title of the channel frame, and of the main frame if appropriate.
  248. */
  249. private void updateTitle() {
  250. final String title = Styliser.stipControlCodes(channelInfo.getName()
  251. + " - " + channelInfo.getTopic());
  252. SwingUtilities.invokeLater(new Runnable() {
  253. public void run() {
  254. frame.setTitle(title);
  255. if (frame.isMaximum() && frame.equals(MainFrame.getMainFrame().getActiveFrame())) {
  256. MainFrame.getMainFrame().setTitle(MainFrame.getMainFrame().getTitlePrefix() + " - " + title);
  257. }
  258. }
  259. });
  260. }
  261. /**
  262. * Joins the specified channel. This only makes sense if used after a call to
  263. * part().
  264. */
  265. public void join() {
  266. server.getParser().joinChannel(channelInfo.getName());
  267. }
  268. /**
  269. * Parts this channel with the specified message. Parting does NOT close the
  270. * channel window.
  271. * @param reason The reason for parting the channel
  272. */
  273. public void part(final String reason) {
  274. server.getParser().partChannel(channelInfo.getName(), reason);
  275. resetWindow();
  276. }
  277. /**
  278. * Resets the window state after the client has left a channel.
  279. */
  280. public void resetWindow() {
  281. onChannel = false;
  282. frame.updateNames(new ArrayList<ChannelClientInfo>());
  283. }
  284. /**
  285. * Parts the channel and then closes the frame.
  286. */
  287. public void close() {
  288. part(configManager.getOption("general", "partmessage"));
  289. closeWindow();
  290. }
  291. /**
  292. * Closes the window without parting the channel.
  293. */
  294. public void closeWindow() {
  295. final CallbackManager callbackManager = server.getParser().getCallbackManager();
  296. for (String callback : CALLBACKS) {
  297. callbackManager.delCallback(callback, this);
  298. }
  299. ActionManager.processEvent(CoreActionType.CHANNEL_CLOSED, null, this);
  300. server.delChannel(channelInfo.getName());
  301. SwingUtilities.invokeLater(new Runnable() {
  302. public void run() {
  303. frame.setVisible(false);
  304. MainFrame.getMainFrame().delChild(frame);
  305. frame = null;
  306. server = null;
  307. }
  308. });
  309. }
  310. /**
  311. * Ensures that a channel client's map is set up correctly.
  312. * @param target The ChannelClientInfo to check
  313. * @deprecated No longer needed, parser instansiates
  314. */
  315. @Deprecated
  316. private void mapClient(final ChannelClientInfo target) {
  317. if (target.getMap() == null) {
  318. target.setMap(new HashMap<ChannelClientProperty, Object>());
  319. }
  320. }
  321. /**
  322. * Called every {general.whotime} seconds to check if the channel needs
  323. * to send a who request.
  324. */
  325. public void checkWho() {
  326. if (onChannel && configManager.getOptionBool("channel", "sendwho")) {
  327. server.getParser().sendLine("WHO :" + channelInfo.getName());
  328. }
  329. }
  330. /** {@inheritDoc} */
  331. public void onChannelMessage(final IRCParser tParser, final ChannelInfo cChannel,
  332. final ChannelClientInfo cChannelClient, final String sMessage, final String sHost) {
  333. String type = "channelMessage";
  334. if (cChannelClient.getClient().equals(tParser.getMyself())) {
  335. type = "channelSelfExternalMessage";
  336. }
  337. final String[] parts = getDetails(cChannelClient);
  338. final String modes = getModes(cChannelClient);
  339. final StringBuffer buff = new StringBuffer(type);
  340. ActionManager.processEvent(CoreActionType.CHANNEL_MESSAGE, buff, this, cChannelClient, sMessage);
  341. frame.addLine(buff, modes, parts[0], parts[1], parts[2], sMessage, cChannel);
  342. }
  343. /** {@inheritDoc} */
  344. public void onChannelAction(final IRCParser tParser, final ChannelInfo cChannel,
  345. final ChannelClientInfo cChannelClient, final String sMessage, final String sHost) {
  346. final String[] parts = getDetails(cChannelClient);
  347. final String modes = getModes(cChannelClient);
  348. String type = "channelAction";
  349. if (parts[0].equals(tParser.getMyself().getNickname())) {
  350. type = "channelSelfExternalAction";
  351. }
  352. final StringBuffer buff = new StringBuffer(type);
  353. ActionManager.processEvent(CoreActionType.CHANNEL_ACTION, buff, this, cChannelClient, sMessage);
  354. frame.addLine(buff, modes, parts[0], parts[1], parts[2], sMessage, cChannel);
  355. }
  356. /** {@inheritDoc} */
  357. public void onChannelGotNames(final IRCParser tParser, final ChannelInfo cChannel) {
  358. frame.updateNames(channelInfo.getChannelClients());
  359. final ArrayList<String> names = new ArrayList<String>();
  360. for (ChannelClientInfo channelClient : cChannel.getChannelClients()) {
  361. mapClient(channelClient);
  362. names.add(channelClient.getNickname());
  363. }
  364. tabCompleter.replaceEntries(names);
  365. tabCompleter.addEntries(CommandManager.getChannelCommandNames());
  366. ActionManager.processEvent(CoreActionType.CHANNEL_GOTNAMES, null, this);
  367. }
  368. /** {@inheritDoc} */
  369. public void onChannelTopic(final IRCParser tParser, final ChannelInfo cChannel,
  370. final boolean bIsJoinTopic) {
  371. if (bIsJoinTopic) {
  372. final StringBuffer buff = new StringBuffer("channelJoinTopic");
  373. ActionManager.processEvent(CoreActionType.CHANNEL_GOTTOPIC, buff, this);
  374. frame.addLine(buff, cChannel.getTopic(), cChannel.getTopicUser(),
  375. 1000 * cChannel.getTopicTime(), cChannel);
  376. } else {
  377. final ChannelClientInfo user = cChannel.getUser(cChannel.getTopicUser());
  378. final String[] parts = ClientInfo.parseHostFull(cChannel.getTopicUser());
  379. final String modes = getModes(user);
  380. final String topic = cChannel.getTopic();
  381. final StringBuffer buff = new StringBuffer("channelTopicChange");
  382. ActionManager.processEvent(CoreActionType.CHANNEL_TOPICCHANGE, buff, this, user, topic);
  383. frame.addLine(buff, modes, parts[0], parts[1], parts[2], cChannel, topic);
  384. }
  385. updateTitle();
  386. }
  387. /** {@inheritDoc} */
  388. public void onChannelJoin(final IRCParser tParser, final ChannelInfo cChannel,
  389. final ChannelClientInfo cChannelClient) {
  390. final ClientInfo client = cChannelClient.getClient();
  391. final StringBuffer buff = new StringBuffer("channelJoin");
  392. mapClient(cChannelClient);
  393. ActionManager.processEvent(CoreActionType.CHANNEL_JOIN, buff, this, cChannelClient);
  394. frame.addLine(buff, "", client.getNickname(), client.getIdent(),
  395. client.getHost(), cChannel);
  396. frame.addName(cChannelClient);
  397. tabCompleter.addEntry(cChannelClient.getNickname());
  398. }
  399. /** {@inheritDoc} */
  400. public void onChannelPart(final IRCParser tParser, final ChannelInfo cChannel,
  401. final ChannelClientInfo cChannelClient, final String sReason) {
  402. final ClientInfo client = cChannelClient.getClient();
  403. final String nick = cChannelClient.getNickname();
  404. final String ident = client.getIdent();
  405. final String host = client.getHost();
  406. final String modes = cChannelClient.getImportantModePrefix();
  407. String type = "";
  408. if (nick.equals(tParser.getMyself().getNickname())) {
  409. if (sReason.length() == 0) {
  410. type = "channelSelfPart";
  411. } else {
  412. type = "channelSelfPartReason";
  413. }
  414. resetWindow();
  415. } else {
  416. if (sReason.length() == 0) {
  417. type = "channelPart";
  418. } else {
  419. type = "channelPartReason";
  420. }
  421. }
  422. final StringBuffer buff = new StringBuffer(type);
  423. ActionManager.processEvent(CoreActionType.CHANNEL_PART, buff, this, cChannelClient, sReason);
  424. frame.addLine(buff, modes, nick, ident, host, cChannel, sReason);
  425. frame.removeName(cChannelClient);
  426. tabCompleter.removeEntry(cChannelClient.getNickname());
  427. }
  428. /** {@inheritDoc} */
  429. public void onChannelKick(final IRCParser tParser, final ChannelInfo cChannel,
  430. final ChannelClientInfo cKickedClient, final ChannelClientInfo cKickedByClient,
  431. final String sReason, final String sKickedByHost) {
  432. final String[] kicker = getDetails(cKickedByClient);
  433. final String kickermodes = getModes(cKickedByClient);
  434. final String victim = cKickedClient.getNickname();
  435. final String victimmodes = cKickedClient.getImportantModePrefix();
  436. final String victimident = cKickedClient.getClient().getIdent();
  437. final String victimhost = cKickedClient.getClient().getHost();
  438. String type = "";
  439. if (sReason.length() == 0) {
  440. type = "channelKick";
  441. } else {
  442. type = "channelKickReason";
  443. }
  444. final StringBuffer buff = new StringBuffer(type);
  445. ActionManager.processEvent(CoreActionType.CHANNEL_KICK, buff, this,
  446. cKickedByClient, cKickedClient, sReason);
  447. frame.addLine(buff, kickermodes, kicker[0], kicker[1], kicker[2], victimmodes,
  448. victim, victimident, victimhost, cChannel.getName(), sReason);
  449. frame.removeName(cKickedClient);
  450. tabCompleter.removeEntry(cKickedClient.getNickname());
  451. if (cKickedClient.getClient().equals(tParser.getMyself())) {
  452. resetWindow();
  453. }
  454. }
  455. /** {@inheritDoc} */
  456. public void onChannelQuit(final IRCParser tParser, final ChannelInfo cChannel,
  457. final ChannelClientInfo cChannelClient, final String sReason) {
  458. final ClientInfo client = cChannelClient.getClient();
  459. final String source = cChannelClient.getNickname();
  460. final String modes = cChannelClient.getImportantModePrefix();
  461. String type = "";
  462. if (sReason.length() == 0) {
  463. type = "channelQuit";
  464. } else {
  465. type = "channelQuitReason";
  466. }
  467. final StringBuffer buff = new StringBuffer(type);
  468. ActionManager.processEvent(CoreActionType.CHANNEL_QUIT, buff, this, cChannelClient, sReason);
  469. frame.addLine(buff, modes, source, client.getIdent(),
  470. client.getHost(), cChannel, sReason);
  471. frame.removeName(cChannelClient);
  472. tabCompleter.removeEntry(cChannelClient.getNickname());
  473. }
  474. /** {@inheritDoc} */
  475. public void onChannelNickChanged(final IRCParser tParser, final ChannelInfo cChannel,
  476. final ChannelClientInfo cChannelClient, final String sOldNick) {
  477. final String modes = cChannelClient.getImportantModePrefix();
  478. final String nick = cChannelClient.getNickname();
  479. final String ident = cChannelClient.getClient().getIdent();
  480. final String host = cChannelClient.getClient().getHost();
  481. String type = "channelNickChange";
  482. if (nick.equals(tParser.getMyself().getNickname())) {
  483. type = "channelSelfNickChange";
  484. }
  485. tabCompleter.removeEntry(sOldNick);
  486. tabCompleter.addEntry(nick);
  487. final StringBuffer buff = new StringBuffer(type);
  488. ActionManager.processEvent(CoreActionType.CHANNEL_NICKCHANGE, buff, this, cChannelClient, sOldNick);
  489. frame.addLine(buff, modes, sOldNick, ident, host, cChannel, nick);
  490. frame.updateNames();
  491. }
  492. /** {@inheritDoc} */
  493. public void onChannelModeChanged(final IRCParser tParser, final ChannelInfo cChannel,
  494. final ChannelClientInfo cChannelClient, final String sHost, final String sModes) {
  495. if (sHost.length() == 0) {
  496. final StringBuffer buff = new StringBuffer();
  497. if (sModes.length() <= 1) {
  498. buff.append("channelNoModes");
  499. } else {
  500. buff.append("channelModeDiscovered");
  501. }
  502. ActionManager.processEvent(CoreActionType.CHANNEL_MODECHANGE, buff, this, cChannelClient, sModes);
  503. frame.addLine(buff, sModes, cChannel.getName());
  504. } else {
  505. final String modes = getModes(cChannelClient);
  506. final String[] details = getDetails(cChannelClient);
  507. final String myNick = tParser.getMyself().getNickname();
  508. String type = "channelModeChange";
  509. if (myNick.equals(cChannelClient.getNickname())) {
  510. type = "channelSelfModeChange";
  511. }
  512. final StringBuffer buff = new StringBuffer(type);
  513. ActionManager.processEvent(CoreActionType.CHANNEL_MODECHANGE, buff, this, cChannelClient, sModes);
  514. frame.addLine(type, modes, details[0], details[1],
  515. details[2], cChannel.getName(), sModes);
  516. }
  517. frame.updateNames();
  518. }
  519. /** {@inheritDoc} */
  520. public void onChannelUserModeChanged(final IRCParser tParser,
  521. final ChannelInfo cChannel, final ChannelClientInfo cChangedClient,
  522. final ChannelClientInfo cSetByClient, final String sHost,
  523. final String sMode) {
  524. if (configManager.getOptionBool("channel", "splitusermodes")) {
  525. final String sourceModes = getModes(cSetByClient);
  526. final String[] sourceHost = getDetails(cSetByClient);
  527. final String targetModes = cChangedClient.getImportantModePrefix();
  528. final String targetNick = cChangedClient.getClient().getNickname();
  529. final String targetIdent = cChangedClient.getClient().getIdent();
  530. final String targetHost = cChangedClient.getClient().getHost();
  531. String format = "channelUserMode_" + sMode;
  532. if (!Formatter.hasFormat(format)) {
  533. format = "channelUserMode_default";
  534. }
  535. frame.addLine(format, sourceModes, sourceHost[0], sourceHost[1],
  536. sourceHost[2], targetModes, targetNick, targetIdent,
  537. targetHost, cChannel, sMode);
  538. }
  539. ActionManager.processEvent(CoreActionType.CHANNEL_USERMODECHANGE, null,
  540. this, cSetByClient, cChangedClient, sMode);
  541. }
  542. /** {@inheritDoc} */
  543. public void onChannelCTCP(final IRCParser tParser,
  544. final ChannelInfo cChannel, final ChannelClientInfo cChannelClient,
  545. final String sType, final String sMessage, final String sHost) {
  546. final String modes = getModes(cChannelClient);
  547. final String[] source = getDetails(cChannelClient);
  548. frame.addLine("channelCTCP", modes, source[0], source[1], source[2],
  549. sType, sMessage, cChannel);
  550. server.sendCTCPReply(source[0], sType, sMessage);
  551. // TODO: Action hook
  552. }
  553. /** {@inheritDoc} */
  554. public void onAwayStateOther(final IRCParser tParser,
  555. final ClientInfo client, final boolean state) {
  556. final ChannelClientInfo channelClient = channelInfo.getUser(client);
  557. if (channelClient != null) {
  558. if (state) {
  559. ActionManager.processEvent(CoreActionType.CHANNEL_USERAWAY,
  560. null, this, channelClient);
  561. } else {
  562. ActionManager.processEvent(CoreActionType.CHANNEL_USERBACK,
  563. null, this, channelClient);
  564. }
  565. }
  566. }
  567. /**
  568. * Returns a string containing the most important mode for the specified client.
  569. * @param channelClient The channel client to check.
  570. * @return A string containing the most important mode, or an empty string
  571. * if there are no (known) modes.
  572. */
  573. private String getModes(final ChannelClientInfo channelClient) {
  574. if (channelClient == null || !configManager.getOptionBool("channel", "showmodeprefix")) {
  575. return "";
  576. } else {
  577. return channelClient.getImportantModePrefix();
  578. }
  579. }
  580. /**
  581. * Returns a string[] containing the nickname/ident/host of the client.
  582. * @param client The channel client to check
  583. * @return A string[] containing displayable components
  584. */
  585. private String[] getDetails(final ChannelClientInfo client) {
  586. final String[] res = new String[3];
  587. res[0] = client.getNickname();
  588. res[1] = client.getClient().getIdent();
  589. res[2] = client.getClient().getHost();
  590. if (configManager.getOptionBool("ui", "shownickcoloursintext")) {
  591. final Map map = client.getMap();
  592. String prefix = null;
  593. Color colour;
  594. if (map.containsKey(ChannelClientProperty.TEXT_FOREGROUND)) {
  595. colour = (Color) map.get(ChannelClientProperty.TEXT_FOREGROUND);
  596. prefix = Styliser.CODE_HEXCOLOUR + ColourManager.getHex(colour);
  597. if (map.containsKey(ChannelClientProperty.TEXT_BACKGROUND)) {
  598. colour = (Color) map.get(ChannelClientProperty.TEXT_BACKGROUND);
  599. prefix = "," + ColourManager.getHex(colour);
  600. }
  601. }
  602. if (prefix != null) {
  603. res[0] = prefix + res[0] + Styliser.CODE_HEXCOLOUR;
  604. }
  605. }
  606. return res;
  607. }
  608. /**
  609. * Returns this channel's name.
  610. * @return A string representation of this channel (i.e., its name)
  611. */
  612. public String toString() {
  613. return channelInfo.getName();
  614. }
  615. }