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.

OsdManager.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Copyright (c) 2006-2015 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.osd;
  23. import com.dmdirc.DMDircMBassador;
  24. import com.dmdirc.addons.ui_swing.UIUtilities;
  25. import com.dmdirc.addons.ui_swing.injection.MainWindow;
  26. import com.dmdirc.config.prefs.CategoryChangeListener;
  27. import com.dmdirc.config.prefs.PluginPreferencesCategory;
  28. import com.dmdirc.config.prefs.PreferencesCategory;
  29. import com.dmdirc.config.prefs.PreferencesDialogModel;
  30. import com.dmdirc.config.prefs.PreferencesInterface;
  31. import com.dmdirc.config.prefs.PreferencesSetting;
  32. import com.dmdirc.config.prefs.PreferencesType;
  33. import com.dmdirc.config.prefs.SettingChangeListener;
  34. import com.dmdirc.events.ClientPrefsOpenedEvent;
  35. import com.dmdirc.interfaces.config.IdentityController;
  36. import com.dmdirc.plugins.PluginDomain;
  37. import com.dmdirc.plugins.PluginInfo;
  38. import com.dmdirc.ui.messages.ColourManager;
  39. import com.dmdirc.ui.messages.ColourManagerFactory;
  40. import com.dmdirc.util.validators.NumericalValidator;
  41. import com.dmdirc.util.validators.OptionalValidator;
  42. import java.awt.Window;
  43. import java.util.ArrayList;
  44. import java.util.HashMap;
  45. import java.util.LinkedList;
  46. import java.util.List;
  47. import java.util.Map;
  48. import java.util.Queue;
  49. import javax.inject.Inject;
  50. import net.engio.mbassy.listener.Handler;
  51. /**
  52. * Class to manage OSD Windows.
  53. */
  54. public class OsdManager implements CategoryChangeListener, PreferencesInterface,
  55. SettingChangeListener {
  56. /** The frame the OSD will be associated with. */
  57. private final Window mainFrame;
  58. /** List of OSD Windows. */
  59. private final List<OsdWindow> windowList = new ArrayList<>();
  60. /** List of messages to be queued. */
  61. private final Queue<QueuedMessage> windowQueue = new LinkedList<>();
  62. /** This plugin's settings domain. */
  63. private final String domain;
  64. /** Config OSD Window. */
  65. private OsdWindow osdWindow;
  66. /** X-axis position of OSD. */
  67. private int x;
  68. /** Y-axis potion of OSD. */
  69. private int y;
  70. /** Setting objects with registered change listeners. */
  71. private PreferencesSetting fontSizeSetting;
  72. private PreferencesSetting backgroundSetting;
  73. private PreferencesSetting foregroundSetting;
  74. private PreferencesSetting widthSetting;
  75. private PreferencesSetting timeoutSetting;
  76. private PreferencesSetting maxWindowsSetting;
  77. /** This plugin's plugin info. */
  78. private final PluginInfo pluginInfo;
  79. private final DMDircMBassador eventBus;
  80. /** The controller to read/write settings with. */
  81. private final IdentityController identityController;
  82. /** The manager to use to parse colours. */
  83. private final ColourManager colourManager;
  84. @Inject
  85. public OsdManager(
  86. @MainWindow final Window mainFrame,
  87. final DMDircMBassador eventBus,
  88. final IdentityController identityController,
  89. final ColourManagerFactory colourManagerFactory,
  90. @PluginDomain(OsdPlugin.class) final PluginInfo pluginInfo) {
  91. this.mainFrame = mainFrame;
  92. this.eventBus = eventBus;
  93. this.identityController = identityController;
  94. this.colourManager = colourManagerFactory.getColourManager(identityController.getGlobalConfiguration());
  95. this.pluginInfo = pluginInfo;
  96. this.domain = pluginInfo.getDomain();
  97. }
  98. /**
  99. * Add messages to the queue and call displayWindows.
  100. *
  101. * @param timeout Time message will be displayed
  102. * @param message Message to be displayed.
  103. */
  104. public void showWindow(final int timeout, final String message) {
  105. windowQueue.add(new QueuedMessage(timeout, message));
  106. displayWindows();
  107. }
  108. /**
  109. * Displays as many windows as appropriate.
  110. */
  111. private synchronized void displayWindows() {
  112. final Integer maxWindows = identityController.getGlobalConfiguration()
  113. .getOptionInt(domain, "maxWindows", false);
  114. QueuedMessage nextItem;
  115. while ((maxWindows == null || getWindowCount() < maxWindows)
  116. && (nextItem = windowQueue.poll()) != null) {
  117. displayWindow(nextItem.getTimeout(), nextItem.getMessage());
  118. }
  119. }
  120. /**
  121. * Create a new OSD window with "message".
  122. * <p>
  123. * This method needs to be synchronised to ensure that the window list is not modified in
  124. * between the invocation of
  125. * {@link OsdPolicy#getYPosition(OsdManager, int)} and the point at which
  126. * the {@link OsdWindow} is added to the windowList.
  127. *
  128. * @see OsdPolicy#getYPosition(OsdManager, int)
  129. * @param message Text to display in the OSD window.
  130. */
  131. private synchronized void displayWindow(final int timeout, final String message) {
  132. final OsdPolicy policy = OsdPolicy.valueOf(
  133. identityController.getGlobalConfiguration().getOption(domain, "newbehaviour")
  134. .toUpperCase());
  135. final int startY = identityController.getGlobalConfiguration()
  136. .getOptionInt(domain, "locationY");
  137. windowList.add(UIUtilities.invokeAndWait(() -> new OsdWindow(
  138. mainFrame,
  139. identityController, this, colourManager,
  140. timeout, message, false,
  141. identityController.getGlobalConfiguration().getOptionInt(
  142. domain, "locationX"), policy.getYPosition(this, startY), domain)));
  143. }
  144. /**
  145. * Destroy the given OSD Window and check if the Queue has items, if so Display them.
  146. *
  147. * @param window The window that we are destroying.
  148. */
  149. public synchronized void closeWindow(final OsdWindow window) {
  150. final OsdPolicy policy = OsdPolicy.valueOf(
  151. identityController.getGlobalConfiguration()
  152. .getOption(domain, "newbehaviour").toUpperCase());
  153. int oldY = window.getDesiredY();
  154. final int closedIndex = windowList.indexOf(window);
  155. if (closedIndex == -1) {
  156. return;
  157. }
  158. windowList.remove(window);
  159. UIUtilities.invokeLater(window::dispose);
  160. final List<OsdWindow> newList = getWindowList();
  161. for (OsdWindow otherWindow : newList.subList(closedIndex, newList.size())) {
  162. final int currentY = otherWindow.getDesiredY();
  163. if (policy.changesPosition()) {
  164. otherWindow.setDesiredLocation(otherWindow.getDesiredX(), oldY);
  165. oldY = currentY;
  166. }
  167. }
  168. displayWindows();
  169. }
  170. /**
  171. * Destroy all OSD Windows.
  172. */
  173. public void closeAll() {
  174. getWindowList().forEach(this::closeWindow);
  175. }
  176. /**
  177. * Get the list of current OSDWindows.
  178. *
  179. * @return a List of all currently open OSDWindows.
  180. */
  181. public List<OsdWindow> getWindowList() {
  182. return new ArrayList<>(windowList);
  183. }
  184. /**
  185. * Get the count of open windows.
  186. *
  187. * @return Current number of OSD Windows open.
  188. */
  189. public int getWindowCount() {
  190. return windowList.size();
  191. }
  192. @Handler
  193. public void showConfig(final ClientPrefsOpenedEvent event) {
  194. final PreferencesDialogModel manager = event.getModel();
  195. x = identityController.getGlobalConfiguration()
  196. .getOptionInt(domain, "locationX");
  197. y = identityController.getGlobalConfiguration()
  198. .getOptionInt(domain, "locationY");
  199. final PreferencesCategory category = new PluginPreferencesCategory(
  200. pluginInfo, "OSD",
  201. "General configuration for OSD plugin.", "category-osd");
  202. fontSizeSetting = new PreferencesSetting(PreferencesType.INTEGER,
  203. domain, "fontSize", "Font size", "Changes the font " + "size of the OSD",
  204. manager.getConfigManager(),
  205. manager.getIdentity()).registerChangeListener(this);
  206. backgroundSetting = new PreferencesSetting(PreferencesType.COLOUR,
  207. domain, "bgcolour", "Background colour",
  208. "Background colour for the OSD", manager.getConfigManager(),
  209. manager.getIdentity()).registerChangeListener(this);
  210. foregroundSetting = new PreferencesSetting(PreferencesType.COLOUR,
  211. domain, "fgcolour", "Foreground colour",
  212. "Foreground colour for the OSD", manager.getConfigManager(),
  213. manager.getIdentity()).registerChangeListener(this);
  214. widthSetting = new PreferencesSetting(PreferencesType.INTEGER,
  215. domain, "width", "OSD Width", "Width of the OSD Window",
  216. manager.getConfigManager(), manager.getIdentity())
  217. .registerChangeListener(this);
  218. timeoutSetting = new PreferencesSetting(PreferencesType.OPTIONALINTEGER,
  219. new OptionalValidator(new NumericalValidator(1, Integer.MAX_VALUE)),
  220. domain, "timeout", "Timeout", "Length of time in "
  221. + "seconds before the OSD window closes", manager.getConfigManager(),
  222. manager.getIdentity());
  223. maxWindowsSetting = new PreferencesSetting(PreferencesType.OPTIONALINTEGER,
  224. new OptionalValidator(new NumericalValidator(1, Integer.MAX_VALUE)),
  225. domain, "maxWindows", "Maximum open windows",
  226. "Maximum number of OSD windows that will be displayed at any given time",
  227. manager.getConfigManager(), manager.getIdentity());
  228. category.addSetting(fontSizeSetting);
  229. category.addSetting(backgroundSetting);
  230. category.addSetting(foregroundSetting);
  231. category.addSetting(widthSetting);
  232. category.addSetting(timeoutSetting);
  233. category.addSetting(maxWindowsSetting);
  234. final Map<String, String> posOptions = new HashMap<>();
  235. //Populate policy MULTICHOICE
  236. for (OsdPolicy policy : OsdPolicy.values()) {
  237. posOptions.put(policy.name(), policy.getDescription());
  238. }
  239. category.addSetting(new PreferencesSetting(domain, "newbehaviour",
  240. "New window policy", "What to do when an OSD Window "
  241. + "is opened when there are other, existing windows open",
  242. posOptions, manager.getConfigManager(), manager.getIdentity()));
  243. category.addChangeListener(this);
  244. manager.getCategory("Plugins").addSubCategory(category);
  245. manager.registerSaveListener(this);
  246. }
  247. @Override
  248. public void categorySelected(final PreferencesCategory category) {
  249. osdWindow = new OsdWindow(mainFrame, identityController, this, colourManager,
  250. -1, "Please drag this OSD to position", true, x, y, domain);
  251. osdWindow.setBackgroundColour(backgroundSetting.getValue());
  252. osdWindow.setForegroundColour(foregroundSetting.getValue());
  253. osdWindow.setFontSize(Integer.parseInt(fontSizeSetting.getValue()));
  254. }
  255. @Override
  256. public void categoryDeselected(final PreferencesCategory category) {
  257. x = osdWindow.getLocationOnScreen().x;
  258. y = osdWindow.getLocationOnScreen().y;
  259. osdWindow.dispose();
  260. osdWindow = null;
  261. }
  262. @Override
  263. public void save() {
  264. identityController.getUserSettings().setOption(domain, "locationX", x);
  265. identityController.getUserSettings().setOption(domain, "locationY", y);
  266. }
  267. @Override
  268. public void settingChanged(final PreferencesSetting setting) {
  269. if (osdWindow == null) {
  270. // They've changed categories but are somehow poking settings.
  271. // Ignore the request.
  272. return;
  273. }
  274. if (setting.equals(fontSizeSetting)) {
  275. osdWindow.setFontSize(Integer.parseInt(setting.getValue()));
  276. } else if (setting.equals(backgroundSetting)) {
  277. osdWindow.setBackgroundColour(setting.getValue());
  278. } else if (setting.equals(foregroundSetting)) {
  279. osdWindow.setForegroundColour(setting.getValue());
  280. } else if (setting.equals(widthSetting)) {
  281. int width = 500;
  282. try {
  283. width = Integer.parseInt(setting.getValue());
  284. } catch (NumberFormatException e) {
  285. //Ignore
  286. }
  287. osdWindow.setSize(width, osdWindow.getHeight());
  288. }
  289. }
  290. public void onLoad() {
  291. eventBus.subscribe(this);
  292. }
  293. public void onUnload() {
  294. eventBus.subscribe(this);
  295. }
  296. }