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.

WritableFrameContainer.java 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (c) 2006-2012 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;
  23. import com.dmdirc.actions.ActionManager;
  24. import com.dmdirc.commandparser.parsers.CommandParser;
  25. import com.dmdirc.config.ConfigManager;
  26. import com.dmdirc.interfaces.actions.ActionType;
  27. import com.dmdirc.messages.MessageSinkManager;
  28. import com.dmdirc.parser.common.CompositionState;
  29. import com.dmdirc.ui.input.TabCompleter;
  30. import java.util.ArrayList;
  31. import java.util.Collection;
  32. import java.util.Date;
  33. import java.util.List;
  34. /**
  35. * The writable frame container adds additional methods to the frame container
  36. * class that allow the sending of lines back to whatever the container's
  37. * data source is (e.g. an IRC channel or server).
  38. */
  39. public abstract class WritableFrameContainer extends FrameContainer {
  40. /** The name of the server notification target. */
  41. protected static final String NOTIFICATION_SERVER = "server".intern();
  42. /** The name of the channel notification target. */
  43. protected static final String NOTIFICATION_CHANNEL = "channel".intern();
  44. /** The command parser used for commands in this container. */
  45. protected final CommandParser commandParser;
  46. /**
  47. * Creates a new WritableFrameContainer.
  48. *
  49. * @param icon The icon to use for this container
  50. * @param name The name of this container
  51. * @param title The title of this container
  52. * @param config The config manager for this container
  53. * @param parser The command parser for this container
  54. * @param components The UI components that this frame requires
  55. * @since 0.6.4
  56. */
  57. public WritableFrameContainer(final String icon, final String name,
  58. final String title, final ConfigManager config,
  59. final CommandParser parser, final Collection<String> components) {
  60. super(icon, name, title, config, components);
  61. this.commandParser = parser;
  62. parser.setOwner(this);
  63. }
  64. /**
  65. * Sends a line of text to this container's source.
  66. *
  67. * @param line The line to be sent
  68. */
  69. public abstract void sendLine(String line);
  70. /**
  71. * Retrieves the command parser to be used for this container.
  72. *
  73. * @return This container's command parser
  74. */
  75. public CommandParser getCommandParser() {
  76. return commandParser;
  77. }
  78. /**
  79. * Retrieves the tab completer which should be used for this cotnainer.
  80. *
  81. * @return This container's tab completer
  82. */
  83. public abstract TabCompleter getTabCompleter();
  84. /**
  85. * Returns the maximum length that a line passed to sendLine() should be,
  86. * in order to prevent it being truncated or causing protocol violations.
  87. *
  88. * @return The maximum line length for this container
  89. */
  90. public abstract int getMaxLineLength();
  91. /**
  92. * Splits the specified line into chunks that contain a number of bytes
  93. * less than or equal to the value returned by {@link #getMaxLineLength()}.
  94. *
  95. * @param line The line to be split
  96. * @return An ordered list of chunks of the desired length
  97. */
  98. protected List<String> splitLine(final String line) {
  99. final List<String> result = new ArrayList<String>();
  100. if (line.indexOf('\n') > -1) {
  101. for (String part : line.split("\n")) {
  102. result.addAll(splitLine(part));
  103. }
  104. } else {
  105. final StringBuilder remaining = new StringBuilder(line);
  106. while (getMaxLineLength() > -1 && remaining.toString().getBytes().length
  107. > getMaxLineLength()) {
  108. int number = Math.min(remaining.length(), getMaxLineLength());
  109. while (remaining.substring(0, number).getBytes().length > getMaxLineLength()) {
  110. number--;
  111. }
  112. result.add(remaining.substring(0, number));
  113. remaining.delete(0, number);
  114. }
  115. result.add(remaining.toString());
  116. }
  117. return result;
  118. }
  119. /**
  120. * Returns the number of lines that the specified string would be sent as.
  121. *
  122. * @param line The string to be split and sent
  123. * @return The number of lines required to send the specified string
  124. */
  125. public final int getNumLines(final String line) {
  126. final String[] splitLines = line.split("(\n|\r\n|\r)", Integer.MAX_VALUE);
  127. int lines = 0;
  128. for (String splitLine : splitLines) {
  129. if (getMaxLineLength() <= 0) {
  130. lines++;
  131. } else {
  132. lines += (int) Math.ceil(splitLine.getBytes().length
  133. / (double) getMaxLineLength());
  134. }
  135. }
  136. return lines;
  137. }
  138. /**
  139. * Processes and displays a notification.
  140. *
  141. * @param messageType The name of the formatter to be used for the message
  142. * @param actionType The action type to be used
  143. * @param args The arguments for the message
  144. * @return True if any further behaviour should be executed, false otherwise
  145. */
  146. public boolean doNotification(final String messageType,
  147. final ActionType actionType, final Object... args) {
  148. return doNotification(new Date(), messageType, actionType, args);
  149. }
  150. /**
  151. * Processes and displays a notification.
  152. *
  153. * @param date The date/time at which the event occured
  154. * @param messageType The name of the formatter to be used for the message
  155. * @param actionType The action type to be used
  156. * @param args The arguments for the message
  157. * @return True if any further behaviour should be executed, false otherwise
  158. */
  159. public boolean doNotification(final Date date, final String messageType,
  160. final ActionType actionType, final Object... args) {
  161. final List<Object> messageArgs = new ArrayList<Object>();
  162. final List<Object> actionArgs = new ArrayList<Object>();
  163. final StringBuffer buffer = new StringBuffer(messageType);
  164. actionArgs.add(this);
  165. for (Object arg : args) {
  166. actionArgs.add(arg);
  167. if (!processNotificationArg(arg, messageArgs)) {
  168. messageArgs.add(arg);
  169. }
  170. }
  171. modifyNotificationArgs(actionArgs, messageArgs);
  172. final boolean res = ActionManager.getActionManager().triggerEvent(
  173. actionType, buffer, actionArgs.toArray());
  174. handleNotification(date, buffer.toString(), messageArgs.toArray());
  175. return res;
  176. }
  177. /**
  178. * Allows subclasses to modify the lists of arguments for notifications.
  179. *
  180. * @param actionArgs The list of arguments to be passed to the actions system
  181. * @param messageArgs The list of arguments to be passed to the formatter
  182. */
  183. protected void modifyNotificationArgs(final List<Object> actionArgs,
  184. final List<Object> messageArgs) {
  185. // Do nothing
  186. }
  187. /**
  188. * Allows subclasses to process specific types of notification arguments.
  189. *
  190. * @param arg The argument to be processed
  191. * @param args The list of arguments that any data should be appended to
  192. * @return True if the arg has been processed, false otherwise
  193. */
  194. protected boolean processNotificationArg(final Object arg, final List<Object> args) {
  195. return false;
  196. }
  197. /**
  198. * Handles general server notifications (i.e., ones not tied to a
  199. * specific window). The user can select where the notifications should
  200. * go in their config.
  201. *
  202. * @param messageType The type of message that is being sent
  203. * @param args The arguments for the message
  204. */
  205. public void handleNotification(final String messageType, final Object... args) {
  206. handleNotification(new Date(), messageType, args);
  207. }
  208. /**
  209. * Handles general server notifications (i.e., ones not tied to a
  210. * specific window). The user can select where the notifications should
  211. * go in their config.
  212. *
  213. * @param date The date/time at which the event occured
  214. * @param messageType The type of message that is being sent
  215. * @param args The arguments for the message
  216. */
  217. public void handleNotification(final Date date, final String messageType, final Object... args) {
  218. MessageSinkManager.getManager().despatchMessage(this, date, messageType, args);
  219. }
  220. /**
  221. * Sets the composition state for the local user for this chat.
  222. *
  223. * @param state The new composition state
  224. */
  225. public void setCompositionState(final CompositionState state) {
  226. // Default implementation does nothing. Subclasses that support
  227. // composition should override this.
  228. }
  229. }