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.

WindowStatusPlugin.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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.windowstatus;
  23. import com.dmdirc.Channel;
  24. import com.dmdirc.FrameContainer;
  25. import com.dmdirc.Query;
  26. import com.dmdirc.Server;
  27. import com.dmdirc.addons.ui_swing.SelectionListener;
  28. import com.dmdirc.addons.ui_swing.SwingController;
  29. import com.dmdirc.addons.ui_swing.UIUtilities;
  30. import com.dmdirc.addons.ui_swing.components.frames.TextFrame;
  31. import com.dmdirc.config.prefs.PluginPreferencesCategory;
  32. import com.dmdirc.config.prefs.PreferencesCategory;
  33. import com.dmdirc.config.prefs.PreferencesDialogModel;
  34. import com.dmdirc.config.prefs.PreferencesSetting;
  35. import com.dmdirc.config.prefs.PreferencesType;
  36. import com.dmdirc.interfaces.ConfigChangeListener;
  37. import com.dmdirc.interfaces.IdentityController;
  38. import com.dmdirc.parser.interfaces.ChannelClientInfo;
  39. import com.dmdirc.parser.interfaces.ChannelInfo;
  40. import com.dmdirc.parser.interfaces.ClientInfo;
  41. import com.dmdirc.plugins.implementations.BasePlugin;
  42. import com.dmdirc.plugins.PluginInfo;
  43. import java.util.HashMap;
  44. import java.util.Map;
  45. import java.util.Map.Entry;
  46. import java.util.concurrent.Callable;
  47. /**
  48. * Displays information related to the current window in the status bar.
  49. */
  50. public final class WindowStatusPlugin extends BasePlugin
  51. implements ConfigChangeListener, SelectionListener {
  52. /** The panel we use in the status bar. */
  53. private final WindowStatusPanel panel;
  54. /** Parent Swing UI. */
  55. private final SwingController controller;
  56. /** Identity controller to read settings from. */
  57. private final IdentityController identityController;
  58. /** Should we show the real name in queries? */
  59. private boolean showname;
  60. /** Should we show users without modes? */
  61. private boolean shownone;
  62. /** Prefix for users without modes. */
  63. private String nonePrefix;
  64. /** This plugin's plugin info. */
  65. private final PluginInfo pluginInfo;
  66. /**
  67. * Creates a new instance of WindowStatusPlugin.
  68. *
  69. * @param pluginInfo This plugin's plugin info.
  70. * @param controller The parent {@link SwingController}.
  71. * @param identityController The controller to read settings from.
  72. */
  73. public WindowStatusPlugin(
  74. final PluginInfo pluginInfo,
  75. final SwingController controller,
  76. final IdentityController identityController) {
  77. super();
  78. this.pluginInfo = pluginInfo;
  79. this.controller = controller;
  80. this.identityController = identityController;
  81. panel = UIUtilities.invokeAndWait(
  82. new Callable<WindowStatusPanel>() {
  83. /** {@inheritDoc} */
  84. @Override
  85. public WindowStatusPanel call() {
  86. return new WindowStatusPanel();
  87. }
  88. });
  89. }
  90. /** {@inheritDoc} */
  91. @Override
  92. public void onLoad() {
  93. controller.getSwingStatusBar().addComponent(panel);
  94. controller.getMainFrame().addSelectionListener(this);
  95. identityController.getGlobalConfiguration().addChangeListener(getDomain(), this);
  96. updateCache();
  97. }
  98. /** {@inheritDoc} */
  99. @Override
  100. public void onUnload() {
  101. controller.getMainFrame().removeSelectionListener(this);
  102. controller.getSwingStatusBar().removeComponent(panel);
  103. }
  104. /** {@inheritDoc} */
  105. @Override
  106. public void selectionChanged(final TextFrame window) {
  107. updateStatus(window == null ? null : window.getContainer());
  108. }
  109. /** Updates the cached config settings. */
  110. private void updateCache() {
  111. showname = identityController.getGlobalConfiguration()
  112. .getOptionBool(getDomain(), "client.showname");
  113. shownone = identityController.getGlobalConfiguration()
  114. .getOptionBool(getDomain(), "channel.shownone");
  115. nonePrefix = identityController.getGlobalConfiguration()
  116. .getOption(getDomain(), "channel.noneprefix");
  117. updateStatus();
  118. }
  119. /** Update the window status using the current active window. */
  120. public void updateStatus() {
  121. final TextFrame active = controller.getMainFrame().getActiveFrame();
  122. if (active != null) {
  123. updateStatus(active.getContainer());
  124. }
  125. }
  126. /**
  127. * Update the window status using a given FrameContainer as the
  128. * active frame.
  129. *
  130. * @param current Window to use when adding status.
  131. */
  132. public void updateStatus(final FrameContainer current) {
  133. if (current == null) {
  134. return;
  135. }
  136. final StringBuffer textString = new StringBuffer();
  137. if (current instanceof Server) {
  138. textString.append(((Server) current).getName());
  139. } else if (current instanceof Channel) {
  140. final ChannelInfo chan = ((Channel) current).getChannelInfo();
  141. final Map<Integer, String> names = new HashMap<>();
  142. final Map<Integer, Integer> types = new HashMap<>();
  143. textString.append(chan.getName());
  144. textString.append(" - Nicks: ");
  145. textString.append(chan.getChannelClientCount());
  146. textString.append(" (");
  147. for (ChannelClientInfo client : chan.getChannelClients()) {
  148. String mode = client.getImportantModePrefix();
  149. final Integer im = client.getClient().getParser()
  150. .getChannelUserModes().indexOf(mode);
  151. if (!names.containsKey(im)) {
  152. if (mode.isEmpty()) {
  153. if (shownone) {
  154. mode = nonePrefix;
  155. } else {
  156. continue;
  157. }
  158. }
  159. names.put(im, mode);
  160. }
  161. Integer count = types.get(im);
  162. if (count == null) {
  163. count = Integer.valueOf(1);
  164. } else {
  165. count++;
  166. }
  167. types.put(im, count);
  168. }
  169. boolean isFirst = true;
  170. for (Entry<Integer, Integer> entry : types.entrySet()) {
  171. if (isFirst) {
  172. isFirst = false;
  173. } else {
  174. textString.append(' ');
  175. }
  176. textString.append(names.get(entry.getKey()));
  177. textString.append(entry.getValue());
  178. }
  179. textString.append(')');
  180. } else if (current instanceof Query) {
  181. final Query frame = (Query) current;
  182. textString.append(frame.getHost());
  183. if (showname && frame.getServer().getParser() != null) {
  184. final ClientInfo client = frame.getServer().getParser()
  185. .getClient(frame.getHost());
  186. final String realname = client.getRealname();
  187. if (realname != null && !realname.isEmpty()) {
  188. textString.append(" - ");
  189. textString.append(client.getRealname());
  190. }
  191. }
  192. } else {
  193. textString.append("???");
  194. }
  195. panel.setText(textString.toString());
  196. }
  197. /** {@inheritDoc} */
  198. @Override
  199. public void showConfig(final PreferencesDialogModel manager) {
  200. final PreferencesCategory category = new PluginPreferencesCategory(
  201. pluginInfo, "Window status", "");
  202. category.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  203. getDomain(), "channel.shownone", "Show 'none' count",
  204. "Should the count for users with no state be shown?",
  205. manager.getConfigManager(), manager.getIdentity()));
  206. category.addSetting(new PreferencesSetting(PreferencesType.TEXT,
  207. getDomain(), "channel.noneprefix", "'None' count prefix",
  208. "The Prefix to use when showing the 'none' count",
  209. manager.getConfigManager(), manager.getIdentity()));
  210. category.addSetting(new PreferencesSetting(PreferencesType.BOOLEAN,
  211. getDomain(), "client.showname", "Show real name",
  212. "Should the realname for clients be shown if known?",
  213. manager.getConfigManager(), manager.getIdentity()));
  214. manager.getCategory("Plugins").addSubCategory(category);
  215. }
  216. /** {@inheritDoc} */
  217. @Override
  218. public void configChanged(final String domain, final String key) {
  219. updateCache();
  220. }
  221. }