PageRenderTime 27ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/integration/boofcv-swing/src/main/java/boofcv/gui/SelectAlgorithmAndInputPanel.java

http://github.com/lessthanoptimal/BoofCV
Java | 331 lines | 193 code | 41 blank | 97 comment | 22 complexity | fa6f502fb907f555a19da2771bc9bc12 MD5 | raw file
  1. /*
  2. * Copyright (c) 2021, Peter Abeles. All Rights Reserved.
  3. *
  4. * This file is part of BoofCV (http://boofcv.org).
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package boofcv.gui;
  19. import boofcv.gui.image.ImagePanel;
  20. import boofcv.io.MediaManager;
  21. import boofcv.io.PathLabel;
  22. import boofcv.io.wrapper.DefaultMediaManager;
  23. import javax.swing.*;
  24. import java.awt.*;
  25. import java.awt.event.ActionEvent;
  26. import java.awt.event.ActionListener;
  27. import java.awt.image.BufferedImage;
  28. import java.io.BufferedReader;
  29. import java.io.IOException;
  30. import java.io.Reader;
  31. import java.io.UncheckedIOException;
  32. import java.util.ArrayList;
  33. import java.util.List;
  34. /**
  35. * Provides pull a menubar for selecting the input source and which algorithm to use
  36. *
  37. * @author Peter Abeles
  38. */
  39. @SuppressWarnings("unchecked")
  40. public abstract class SelectAlgorithmAndInputPanel extends JPanel
  41. implements ActionListener, VisualizeApp {
  42. JToolBar toolbar;
  43. // each combo box is used to select different algorithms
  44. JComboBox[] algBoxes;
  45. // used to select the input image
  46. JComboBox imageBox;
  47. // when selected it shows the original image
  48. protected JCheckBox originalCheck;
  49. List<Object>[] algCookies;
  50. // list of input names and where to get the inputs
  51. protected List<PathLabel> inputRefs;
  52. protected String baseDirectory = "";
  53. // components which had been externally added
  54. List<JComponent> addedComponents = new ArrayList<>();
  55. // what the original image was before any processing
  56. protected BufferedImage inputImage;
  57. // panel used for displaying the original image
  58. ImagePanel origPanel = new ImagePanel();
  59. // the main GUI being displayed
  60. Component gui;
  61. // should it post algorithm change events yet?
  62. boolean postAlgorithmEvents = false;
  63. // abstract way of reading in media
  64. protected MediaManager media = DefaultMediaManager.INSTANCE;
  65. protected SelectAlgorithmAndInputPanel( int numAlgFamilies ) {
  66. super(new BorderLayout());
  67. toolbar = new JToolBar();
  68. imageBox = new JComboBox<>();
  69. toolbar.add(imageBox);
  70. imageBox.addActionListener(this);
  71. imageBox.setMaximumSize(imageBox.getPreferredSize());
  72. algBoxes = new JComboBox[numAlgFamilies];
  73. algCookies = new List[numAlgFamilies];
  74. for (int i = 0; i < numAlgFamilies; i++) {
  75. var b = algBoxes[i] = new JComboBox<>();
  76. toolbar.add(b);
  77. b.addActionListener(this);
  78. b.setMaximumSize(b.getPreferredSize());
  79. algCookies[i] = new ArrayList<>();
  80. }
  81. toolbar.add(Box.createHorizontalGlue());
  82. originalCheck = new JCheckBox("Show Input");
  83. toolbar.add(originalCheck);
  84. originalCheck.addActionListener(this);
  85. originalCheck.setEnabled(false);
  86. add(toolbar, BorderLayout.PAGE_START);
  87. }
  88. /**
  89. * Loads a standardized file for input references
  90. *
  91. * @param fileName path to config file
  92. */
  93. @Override
  94. public void loadInputData( String fileName ) {
  95. Reader r = media.openFile(fileName);
  96. List<PathLabel> refs = new ArrayList<>();
  97. try {
  98. BufferedReader reader = new BufferedReader(r);
  99. String line;
  100. while ((line = reader.readLine()) != null) {
  101. String[] z = line.split(":");
  102. String[] names = new String[z.length - 1];
  103. for (int i = 1; i < z.length; i++) {
  104. names[i - 1] = baseDirectory + z[i];
  105. }
  106. refs.add(new PathLabel(z[0], names));
  107. }
  108. setInputList(refs);
  109. } catch (IOException e) {
  110. throw new UncheckedIOException(e);
  111. }
  112. }
  113. /**
  114. * Sets the directory that relative references are relative too
  115. */
  116. public void setBaseDirectory( String baseDirectory ) {
  117. this.baseDirectory = baseDirectory;
  118. }
  119. /**
  120. * Adds a new component into the toolbar.
  121. *
  122. * @param comp The component being added
  123. */
  124. public void addToToolbar( JComponent comp ) {
  125. toolbar.add(comp, 1 + algBoxes.length);
  126. toolbar.revalidate();
  127. addedComponents.add(comp);
  128. }
  129. public void removeFromToolbar( JComponent comp ) {
  130. toolbar.remove(comp);
  131. toolbar.revalidate();
  132. addedComponents.remove(comp);
  133. }
  134. /**
  135. * Used to add the main GUI to this panel. Must use this function.
  136. * Algorithm change events will not be posted until this function has been set.
  137. *
  138. * @param gui The main GUI being displayed.
  139. */
  140. public void setMainGUI( final Component gui ) {
  141. postAlgorithmEvents = true;
  142. this.gui = gui;
  143. SwingUtilities.invokeLater(() -> add(gui, BorderLayout.CENTER));
  144. }
  145. /**
  146. * Specifies an image which contains the original input image. After this has been called the
  147. * view input image widget is activated and when selected this image will be displayed instead
  148. * of the main GUI. This functionality is optional.
  149. *
  150. * @param image Original input image.
  151. */
  152. public void setInputImage( BufferedImage image ) {
  153. inputImage = image;
  154. SwingUtilities.invokeLater(() -> {
  155. if (inputImage == null) {
  156. originalCheck.setEnabled(false);
  157. } else {
  158. originalCheck.setEnabled(true);
  159. origPanel.setImage(inputImage);
  160. origPanel.setPreferredSize(new Dimension(inputImage.getWidth(), inputImage.getHeight()));
  161. origPanel.repaint();
  162. }
  163. });
  164. }
  165. /**
  166. * Specifies a list of images to use as input and loads them
  167. *
  168. * @param inputRefs Name of input and where to get it
  169. */
  170. public void setInputList( final List<PathLabel> inputRefs ) {
  171. this.inputRefs = inputRefs;
  172. SwingUtilities.invokeLater(() -> {
  173. for (int i = 0; i < inputRefs.size(); i++) {
  174. imageBox.addItem(inputRefs.get(i).getLabel());
  175. }
  176. });
  177. }
  178. public void addAlgorithm( final int indexFamily, final String name, Object cookie ) {
  179. algCookies[indexFamily].add(cookie);
  180. SwingUtilities.invokeLater(() -> algBoxes[indexFamily].addItem(name));
  181. }
  182. /**
  183. * Grabs the currently selected algorithm, passes information to GUI for updating, toggles GUI
  184. * being active/not. refreshAll() is called in a new thread.
  185. */
  186. public void doRefreshAll() {
  187. SwingUtilities.invokeLater(() -> {
  188. // collect the current state inside the GUI thread
  189. final Object[] state = new Object[algCookies.length];
  190. for (int i = 0; i < state.length; i++) {
  191. state[i] = algCookies[i].get(algBoxes[i].getSelectedIndex());
  192. }
  193. // create a new thread to process this change
  194. new Thread(() -> {
  195. setActiveGUI(false);
  196. refreshAll(state);
  197. setActiveGUI(true);
  198. }).start();
  199. });
  200. }
  201. /**
  202. * Enables/disables the ability to interact with the algorithms GUI.
  203. */
  204. private void setActiveGUI( final boolean isEnabled ) {
  205. SwingUtilities.invokeLater(() -> {
  206. toolbar.setEnabled(isEnabled);
  207. for (JComboBox<?> b : algBoxes) {
  208. b.setEnabled(isEnabled);
  209. }
  210. for (JComponent b : addedComponents) {
  211. b.setEnabled(isEnabled);
  212. }
  213. imageBox.setEnabled(isEnabled);
  214. });
  215. }
  216. /**
  217. * Returns the cookie associated with the specified algorithm family.
  218. */
  219. protected <T> T getAlgorithmCookie( int indexFamily ) {
  220. return (T)algCookies[indexFamily].get(algBoxes[indexFamily].getSelectedIndex());
  221. }
  222. @Override
  223. public void actionPerformed( ActionEvent e ) {
  224. for (int i = 0; i < algBoxes.length; i++) {
  225. if (algBoxes[i] == e.getSource()) {
  226. // see if its ready to start posting these events
  227. if (!postAlgorithmEvents)
  228. return;
  229. // notify the main GUI to change the input algorithm
  230. final Object cookie = algCookies[i].get(algBoxes[i].getSelectedIndex());
  231. final String name = (String)algBoxes[i].getSelectedItem();
  232. final int indexFamily = i;
  233. new Thread(() -> performSetAlgorithm(indexFamily, name, cookie)).start();
  234. return;
  235. }
  236. }
  237. if (e.getSource() == imageBox) {
  238. // notify the main GUI to change the input image
  239. final String name = (String)imageBox.getSelectedItem();
  240. new Thread(() -> performChangeInput(name, imageBox.getSelectedIndex())).start();
  241. } else if (e.getSource() == originalCheck) {
  242. origPanel.setSize(gui.getWidth(), gui.getHeight());
  243. // swap the main GUI with a picture of the original input image
  244. if (originalCheck.isSelected()) {
  245. remove(gui);
  246. add(origPanel);
  247. } else {
  248. remove(origPanel);
  249. add(gui);
  250. }
  251. validate();
  252. repaint();
  253. }
  254. }
  255. private void performSetAlgorithm( int indexFamily, String name, Object cookie ) {
  256. setActiveGUI(false);
  257. setActiveAlgorithm(indexFamily, name, cookie);
  258. setActiveGUI(true);
  259. }
  260. private void performChangeInput( String name, int index ) {
  261. setActiveGUI(false);
  262. changeInput(name, index);
  263. setActiveGUI(true);
  264. }
  265. @Override
  266. public void setMediaManager( MediaManager manager ) {
  267. this.media = manager;
  268. }
  269. /**
  270. * Provides the current state of all selected algorithms.
  271. *
  272. * @param cookies state of each selected algorithm.
  273. */
  274. public abstract void refreshAll( Object[] cookies );
  275. /**
  276. * A request has been made to change the processing algorithm. NOT called from a GUI thread.
  277. *
  278. * @param name Display name of the algorithm.
  279. * @param cookie Reference to user defined data.
  280. */
  281. public abstract void setActiveAlgorithm( int indexFamily, String name, Object cookie );
  282. /**
  283. * A request to change the input image has been made. The input image's label and its index in the
  284. * manager are returned.
  285. *
  286. * @param name Display name of the image.
  287. * @param index Which image in the list.
  288. */
  289. public abstract void changeInput( String name, int index );
  290. }