/** * Creates the buttons panel. * * @return the buttons panel */ private Component createButtonsPanel() { JPanel buttonsPanel = new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); JButton okButton = new JButton(GuiActivator.getResources().getI18NString("service.gui.OK")); okButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { selectedDevice = (MediaDevice) deviceComboBox.getSelectedItem(); dispose(); } }); buttonsPanel.add(okButton); cancelButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { selectedDevice = null; dispose(); } }); buttonsPanel.add(cancelButton); return buttonsPanel; }
/** Sets the names of the call buttons depending on the chat session type. */ private void setCallButtonsName() { if (chatSession instanceof ConferenceChatSession) { callButton.setName("createConference"); callVideoButton.setName("createConference"); this.callButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CREATE_JOIN_VIDEO_CONFERENCE")); this.callVideoButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CREATE_JOIN_VIDEO_CONFERENCE")); } else { callButton.setName("call"); callVideoButton.setName("callVideo"); this.callButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT")); this.callVideoButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT")); } }
private void initSmiliesSelectorBox() { this.smileysBox = new SmileysSelectorBox(); this.smileysBox.setName("smiley"); this.smileysBox.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.INSERT_SMILEY") + " Ctrl-M"); SIPCommMenuBar smileyMenuBar = new SIPCommMenuBar(); smileyMenuBar.setOpaque(false); smileyMenuBar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); smileyMenuBar.add(smileysBox); this.add(smileyMenuBar); }
/** * Creates an instance of <tt>ShowPreviewDialog</tt> * * @param chatPanel The <tt>ChatConversationPanel</tt> that is associated with this dialog. */ ShowPreviewDialog(final ChatConversationPanel chatPanel) { this.chatPanel = chatPanel; this.setTitle( GuiActivator.getResources().getI18NString("service.gui.SHOW_PREVIEW_DIALOG_TITLE")); okButton = new JButton(GuiActivator.getResources().getI18NString("service.gui.OK")); cancelButton = new JButton(GuiActivator.getResources().getI18NString("service.gui.CANCEL")); JPanel mainPanel = new TransparentPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // mainPanel.setPreferredSize(new Dimension(200, 150)); this.getContentPane().add(mainPanel); JTextPane descriptionMsg = new JTextPane(); descriptionMsg.setEditable(false); descriptionMsg.setOpaque(false); descriptionMsg.setText( GuiActivator.getResources().getI18NString("service.gui.SHOW_PREVIEW_WARNING_DESCRIPTION")); Icon warningIcon = null; try { warningIcon = new ImageIcon( ImageIO.read( GuiActivator.getResources().getImageURL("service.gui.icons.WARNING_ICON"))); } catch (IOException e) { logger.debug("failed to load the warning icon"); } JLabel warningSign = new JLabel(warningIcon); JPanel warningPanel = new TransparentPanel(); warningPanel.setLayout(new BoxLayout(warningPanel, BoxLayout.X_AXIS)); warningPanel.add(warningSign); warningPanel.add(Box.createHorizontalStrut(10)); warningPanel.add(descriptionMsg); enableReplacement = new JCheckBox( GuiActivator.getResources() .getI18NString("plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS")); enableReplacement.setOpaque(false); enableReplacement.setSelected(cfg.getBoolean(ReplacementProperty.REPLACEMENT_ENABLE, true)); enableReplacementProposal = new JCheckBox( GuiActivator.getResources() .getI18NString("plugin.chatconfig.replacement.ENABLE_REPLACEMENT_PROPOSAL")); enableReplacementProposal.setOpaque(false); JPanel checkBoxPanel = new TransparentPanel(); checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS)); checkBoxPanel.add(enableReplacement); checkBoxPanel.add(enableReplacementProposal); JPanel buttonsPanel = new TransparentPanel(new FlowLayout(FlowLayout.CENTER)); buttonsPanel.add(okButton); buttonsPanel.add(cancelButton); mainPanel.add(warningPanel); mainPanel.add(Box.createVerticalStrut(10)); mainPanel.add(checkBoxPanel); mainPanel.add(buttonsPanel); okButton.addActionListener(this); cancelButton.addActionListener(this); this.setPreferredSize(new Dimension(390, 230)); }
/** Initializes this component. */ protected void init() { this.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 0)); this.setOpaque(false); this.add(inviteButton); // if we leave a chat room when we close the window // there is no need for this button if (!ConfigurationUtils.isLeaveChatRoomOnWindowCloseEnabled()) this.add(leaveChatRoomButton); this.add(callButton); this.add(callVideoButton); this.add(desktopSharingButton); this.add(sendFileButton); ChatPanel chatPanel = chatContainer.getCurrentChat(); if (chatPanel == null || !(chatPanel.getChatSession() instanceof MetaContactChatSession)) sendFileButton.setEnabled(false); this.addSeparator(); this.add(historyButton); this.add(previousButton); this.add(nextButton); // We only add the options button if the property SHOW_OPTIONS_WINDOW // specifies so or if it's not set. Boolean showOptionsProp = GuiActivator.getConfigurationService() .getBoolean(ConfigurationFrame.SHOW_OPTIONS_WINDOW_PROPERTY, false); if (showOptionsProp.booleanValue()) { this.add(optionsButton); } this.addSeparator(); if (ConfigurationUtils.isFontSupportEnabled()) { this.add(fontButton); fontButton.setName("font"); fontButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CHANGE_FONT")); fontButton.addActionListener(this); } initSmiliesSelectorBox(); this.addSeparator(); this.inviteButton.setName("invite"); this.inviteButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.INVITE")); this.leaveChatRoomButton.setName("leave"); this.leaveChatRoomButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.LEAVE")); this.callButton.setName("call"); this.callButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT")); this.callVideoButton.setName("callVideo"); this.callVideoButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT")); this.desktopSharingButton.setName("desktop"); this.desktopSharingButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.SHARE_DESKTOP_WITH_CONTACT")); this.historyButton.setName("history"); this.historyButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.HISTORY") + " Ctrl-H"); optionsButton.setName("options"); optionsButton.setToolTipText(GuiActivator.getResources().getI18NString("service.gui.OPTIONS")); this.sendFileButton.setName("sendFile"); this.sendFileButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.SEND_FILE")); this.previousButton.setName("previous"); this.previousButton.setToolTipText( GuiActivator.getResources().getI18NString("service.gui.PREVIOUS")); this.nextButton.setName("next"); this.nextButton.setToolTipText(GuiActivator.getResources().getI18NString("service.gui.NEXT")); inviteButton.addActionListener(this); leaveChatRoomButton.addActionListener(this); callButton.addActionListener(this); callVideoButton.addActionListener(this); desktopSharingButton.addActionListener(this); historyButton.addActionListener(this); optionsButton.addActionListener(this); sendFileButton.addActionListener(this); previousButton.addActionListener(this); nextButton.addActionListener(this); }
/** * The button that starts/stops the call recording. * * @author Dmitri Melnikov * @author Lubomir Marinov */ public class RecordButton extends AbstractCallToggleButton { /** The logger used by the <tt>RecordButton</tt> class and its instances for logging output. */ private static final Logger logger = Logger.getLogger(RecordButton.class); /** The date format used in file names. */ private static final SimpleDateFormat FORMAT = new SimpleDateFormat("*****@*****.**"); /** Configuration service. */ private static final ConfigurationService configuration = GuiActivator.getConfigurationService(); /** Resource service. */ private static final ResourceManagementService resources = GuiActivator.getResources(); /** Maximum allowed file name length. */ private static final int MAX_FILENAME_LENGTH = 64; /** The full filename of the saved call on the file system. */ private String callFilename; /** Call file chooser. */ private SipCommFileChooser callFileChooser; /** * The <tt>Recorder</tt> which is depicted by this <tt>RecordButton</tt> and which is to record or * records {@link #call} into {@link #callFilename}. */ private Recorder recorder; /** * Initializes a new <tt>RecordButton</tt> instance which is to record the audio stream. * * @param call the <tt>Call</tt> to be associated with the new instance and to have the audio * stream recorded */ public RecordButton(Call call) { this(call, false); } /** * Initializes a new <tt>RecordButton</tt> instance which is to record the audio stream. * * @param call the <tt>Call</tt> to be associated with the new instance and to have its audio * stream recorded * @param selected <tt>true</tt> if the new toggle button is to be initially selected; otherwise, * <tt>false</tt> */ public RecordButton(Call call, boolean selected) { super(call, true, selected, ImageLoader.RECORD_BUTTON, ImageLoader.RECORD_BUTTON_PRESSED, null); String toolTip = resources.getI18NString("service.gui.RECORD_BUTTON_TOOL_TIP"); String saveDir = configuration.getString(Recorder.SAVED_CALLS_PATH); if ((saveDir != null) && (saveDir.length() != 0)) toolTip += " (" + saveDir + ")"; setToolTipText(toolTip); } /** Starts/stops the recording of the call when this button is pressed. */ @Override public void buttonPressed() { if (call != null) { // start recording if (isSelected()) { boolean startedRecording = false; try { startedRecording = startRecording(); } finally { if (!startedRecording && (recorder != null)) { try { recorder.stop(); } finally { recorder = null; } } setSelected(startedRecording); } } // stop recording else if (recorder != null) { try { recorder.stop(); } finally { recorder = null; setSelected(false); } } } } /** * Creates a full filename for the call by combining the directory, file prefix and extension. If * the directory is <tt>null</tt> user's home directory is used. * * @param savedCallsPath the path to the directory in which the generated file name is to be * placed * @return a full filename for the call */ private String createDefaultFilename(String savedCallsPath) { // set to user's home when null if (savedCallsPath == null) { try { savedCallsPath = GuiActivator.getFileAccessService().getDefaultDownloadDirectory().getAbsolutePath(); } catch (IOException ioex) { // Leave it in the current directory. } } String ext = configuration.getString(Recorder.FORMAT); // Use a default format when the configured one seems invalid. if ((ext == null) || (ext.length() == 0) || !isSupportedFormat(ext)) ext = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; return ((savedCallsPath == null) ? "" : (savedCallsPath + File.separator)) + generateCallFilename(ext); } /** * Generates a file name for the call based on the current date and the names of the peers in the * call. * * @param ext file extension * @return the file name for the call */ private String generateCallFilename(String ext) { String filename = FORMAT.format(new Date()) + "-call"; int maxLength = MAX_FILENAME_LENGTH - 2 - filename.length() - ext.length(); String peerName = getCallPeerName(maxLength); filename += ((!peerName.equals("")) ? "-" : "") + peerName + "." + ext; return filename; } /** * Gets and formats the names of the peers in the call. * * @param maxLength maximum length of the filename * @return the name of the peer in the call formated */ private String getCallPeerName(int maxLength) { List<CallPeer> callPeers = call.getConference().getCallPeers(); CallPeer callPeer = null; String peerName = ""; if (!callPeers.isEmpty()) { callPeer = callPeers.get(0); if (callPeer != null) { peerName = callPeer.getDisplayName(); peerName = peerName.replaceAll("[^\\da-zA-Z\\_\\-@\\.]", ""); if (peerName.length() > maxLength) { peerName = peerName.substring(0, maxLength); } } } return peerName; } /** * Gets the <tt>Recorder</tt> represented by this <tt>RecordButton</tt> creating it first if it * does not exist. * * @return the <tt>Recorder</tt> represented by this <tt>RecordButton</tt> created first if it * does not exist * @throws OperationFailedException if anything goes wrong while creating the <tt>Recorder</tt> to * be represented by this <tt>RecordButton</tt> */ private Recorder getRecorder() throws OperationFailedException { if (recorder == null) { OperationSetBasicTelephony<?> telephony = call.getProtocolProvider().getOperationSet(OperationSetBasicTelephony.class); recorder = telephony.createRecorder(call); } return recorder; } /** * Determines whether the extension of a specific <tt>File</tt> specifies a format supported by * the <tt>Recorder</tt> represented by this <tt>RecordButton</tt>. * * @param file the <tt>File</tt> whose extension is to be checked whether it specifies a format * supported by the <tt>Recorder</tt> represented by this <tt>RecordButton</tt> * @return <tt>true</tt> if the extension of the specified <tt>file</tt> specifies a format * supported by the <tt>Recorder</tt> represented by this <tt>RecordButton</tt>; otherwise, * <tt>false</tt> */ private boolean isSupportedFormat(File file) { String extension = SoundFileUtils.getExtension(file); return (extension != null) && (extension.length() != 0) && isSupportedFormat(extension); } /** * Determines whether a specific format is supported by the <tt>Recorder</tt> represented by this * <tt>RecordButton</tt>. * * @param format the format which is to be checked whether it is supported by the * <tt>Recorder</tt> represented by this <tt>RecordButton</tt> * @return <tt>true</tt> if the specified <tt>format</tt> is supported by the <tt>Recorder</tt> * represented by this <tt>RecordButton</tt>; otherwise, <tt>false</tt> */ private boolean isSupportedFormat(String format) { Recorder recorder; try { recorder = getRecorder(); } catch (OperationFailedException ofex) { logger.error("Failed to get Recorder", ofex); return false; } List<String> supportedFormats = recorder.getSupportedFormats(); return (supportedFormats != null) && supportedFormats.contains(format); } /** * Starts recording {@link #call} creating {@link #recorder} first and asking the user for the * recording format and file if they are not configured in the "Call Recording" configuration * form. * * @return <tt>true</tt> if the recording has been started successfully; otherwise, <tt>false</tt> */ private boolean startRecording() { String savedCallsPath = configuration.getString(Recorder.SAVED_CALLS_PATH); String callFormat; // Ask the user where to save the call. if ((savedCallsPath == null) || (savedCallsPath.length() == 0)) { /* * Delay the initialization of callFileChooser in order to delay the * creation of the recorder. */ if (callFileChooser == null) { callFileChooser = GenericFileDialog.create( null, resources.getI18NString("plugin.callrecordingconfig.SAVE_CALL"), SipCommFileChooser.SAVE_FILE_OPERATION); callFileChooser.addFilter( new SipCommFileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || isSupportedFormat(f); } @Override public String getDescription() { StringBuilder description = new StringBuilder(); description.append("Recorded call"); Recorder recorder; try { recorder = getRecorder(); } catch (OperationFailedException ofex) { logger.error("Failed to get Recorder", ofex); recorder = null; } if (recorder != null) { List<String> supportedFormats = recorder.getSupportedFormats(); if (supportedFormats != null) { description.append(" ("); boolean firstSupportedFormat = true; for (String supportedFormat : supportedFormats) { if (firstSupportedFormat) firstSupportedFormat = false; else description.append(", "); description.append("*."); description.append(supportedFormat); } description.append(')'); } } return description.toString(); } }); } // Offer a default name for the file to record into. callFileChooser.setStartPath(createDefaultFilename(null)); File selectedFile = callFileChooser.getFileFromDialog(); if (selectedFile != null) { callFilename = selectedFile.getAbsolutePath(); /* * If the user specified no extension (which seems common on Mac * OS X at least) i.e. no format, then it is not obvious that we * have to override the set Recorder.CALL_FORMAT. */ callFormat = SoundFileUtils.getExtension(selectedFile); if ((callFormat != null) && (callFormat.length() != 0)) { /* * If the use has specified an extension and thus a format * which is not supported, use a default format instead. */ if (!isSupportedFormat(selectedFile)) { /* * If what appears to be an extension seems a lot like * an extension, then it should be somewhat safer to * replace it. */ if (SoundFileUtils.isSoundFile(selectedFile)) { callFilename = callFilename.substring(0, callFilename.lastIndexOf('.')); } String configuredFormat = configuration.getString(Recorder.FORMAT); callFormat = (configuredFormat != null && configuredFormat.length() != 0) ? configuredFormat : SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; callFilename += '.' + callFormat; } configuration.setProperty(Recorder.FORMAT, callFormat); } } else { // user canceled the recording return false; } } else { callFilename = createDefaultFilename(savedCallsPath); callFormat = SoundFileUtils.getExtension(new File(callFilename)); } Throwable exception = null; try { Recorder recorder = getRecorder(); if (recorder != null) { if ((callFormat == null) || (callFormat.length() <= 0)) callFormat = SoundFileUtils.DEFAULT_CALL_RECORDING_FORMAT; recorder.start(callFormat, callFilename); } this.recorder = recorder; } catch (IOException ioex) { exception = ioex; } catch (MediaException mex) { exception = mex; } catch (OperationFailedException ofex) { exception = ofex; } if ((recorder == null) || (exception != null)) { logger.error( "Failed to start recording call " + call + " into file " + callFilename, exception); return false; } else return true; } }
/** Creates a file conversation component. */ public FileTransferConversationComponent() { imageLabel = new FileImageLabel(); constraints.gridx = 0; constraints.gridy = 0; constraints.gridwidth = 1; constraints.gridheight = 4; constraints.anchor = GridBagConstraints.NORTHWEST; constraints.insets = new Insets(5, 5, 5, 5); add(imageLabel, constraints); imageLabel.setIcon(new ImageIcon(ImageLoader.getImage(ImageLoader.DEFAULT_FILE_ICON))); constraints.gridx = 1; constraints.gridy = 0; constraints.gridwidth = 3; constraints.gridheight = 1; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.weightx = 1.0; constraints.anchor = GridBagConstraints.NORTHWEST; constraints.insets = new Insets(5, 5, 5, 5); add(titleLabel, constraints); titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 11f)); constraints.gridx = 1; constraints.gridy = 1; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 5, 5); add(fileLabel, constraints); constraints.gridx = 1; constraints.gridy = 2; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.fill = GridBagConstraints.NONE; add(errorIconLabel, constraints); errorIconLabel.setVisible(false); constraints.gridx = 2; constraints.gridy = 2; constraints.gridwidth = 2; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.fill = GridBagConstraints.HORIZONTAL; add(errorArea, constraints); errorArea.setForeground(new Color(resources.getColor("service.gui.ERROR_FOREGROUND"))); setTextAreaStyle(errorArea); errorArea.setVisible(false); constraints.gridx = 1; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); add(retryButton, constraints); retryButton.setText(GuiActivator.getResources().getI18NString("service.gui.RETRY")); retryButton.setVisible(false); constraints.gridx = 1; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); add(cancelButton, constraints); cancelButton.setText(GuiActivator.getResources().getI18NString("service.gui.CANCEL")); cancelButton.addActionListener(this); cancelButton.setVisible(false); constraints.gridx = 2; constraints.gridy = 3; constraints.gridwidth = GridBagConstraints.RELATIVE; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; constraints.insets = new Insets(0, 5, 0, 5); constraints.gridx = 3; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.LINE_END; constraints.insets = new Insets(0, 5, 0, 5); add(progressPropertiesPanel, constraints); estimatedTimeLabel.setFont(estimatedTimeLabel.getFont().deriveFont(11f)); estimatedTimeLabel.setVisible(false); progressSpeedLabel.setFont(progressSpeedLabel.getFont().deriveFont(11f)); progressSpeedLabel.setVisible(false); progressPropertiesPanel.add(progressSpeedLabel); progressPropertiesPanel.add(estimatedTimeLabel); constraints.gridx = 1; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.fill = GridBagConstraints.NONE; add(acceptButton, constraints); acceptButton.setText(GuiActivator.getResources().getI18NString("service.gui.ACCEPT")); acceptButton.setVisible(false); constraints.gridx = 2; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.fill = GridBagConstraints.NONE; add(rejectButton, constraints); rejectButton.setText(GuiActivator.getResources().getI18NString("service.gui.REJECT")); rejectButton.setVisible(false); constraints.gridx = 1; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.fill = GridBagConstraints.NONE; add(openFileButton, constraints); openFileButton.setText(GuiActivator.getResources().getI18NString("service.gui.OPEN")); openFileButton.setVisible(false); openFileButton.addActionListener(this); constraints.gridx = 2; constraints.gridy = 3; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 0.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.fill = GridBagConstraints.NONE; add(openFolderButton, constraints); openFolderButton.setText(GuiActivator.getResources().getI18NString("service.gui.OPEN_FOLDER")); openFolderButton.setVisible(false); openFolderButton.addActionListener(this); constraints.gridx = 1; constraints.gridy = 2; constraints.gridwidth = 3; constraints.gridheight = 1; constraints.weightx = 1.0; constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(0, 5, 0, 5); constraints.ipadx = 150; constraints.fill = GridBagConstraints.HORIZONTAL; add(progressBar, constraints); progressBar.setVisible(false); progressBar.setStringPainted(true); }
/** * A dialog dedicated to desktop streaming/sharing. Shows the possible screens to select from to use * for the streaming/sharing session. * * @author Yana Stamcheva */ public class SelectScreenDialog extends SIPCommDialog { /** Serial version UID. */ private static final long serialVersionUID = 0L; /** The object used for logging. */ private static final Logger logger = Logger.getLogger(SelectScreenDialog.class); /** The combo box containing screen choice. */ private final JComboBox deviceComboBox; /** The cancel button of this dialog. */ private final JButton cancelButton = new JButton(GuiActivator.getResources().getI18NString("service.gui.CANCEL")); /** * The video <code>CaptureDeviceInfo</code> this instance started to create the preview of. * * <p>Because the creation of the preview is asynchronous, it's possible to request the preview of * one and the same device multiple times. Which may lead to failures because of, for example, * busy devices and/or resources (as is the case with LTI-CIVIL and video4linux2). */ private static MediaDevice videoDeviceInPreview; /** The selected media device. */ private MediaDevice selectedDevice; /** * Creates an instance of <tt>SelectScreenDialog</tt> by specifying the list of possible desktop * devices to choose from. * * @param desktopDevices the list of possible desktop devices to choose from */ public SelectScreenDialog(List<MediaDevice> desktopDevices) { setModal(true); setPreferredSize(new Dimension(400, 300)); Container contentPane = getContentPane(); contentPane.setLayout(new BorderLayout()); deviceComboBox = new JComboBox(desktopDevices.toArray()); contentPane.add(deviceComboBox, BorderLayout.NORTH); deviceComboBox.setRenderer(new ComboRenderer()); contentPane.add(createPreview(deviceComboBox)); contentPane.add(createButtonsPanel(), BorderLayout.SOUTH); } /** * Returns the selected device. * * @return the selected device */ public MediaDevice getSelectedDevice() { return selectedDevice; } /** * Creates the buttons panel. * * @return the buttons panel */ private Component createButtonsPanel() { JPanel buttonsPanel = new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); JButton okButton = new JButton(GuiActivator.getResources().getI18NString("service.gui.OK")); okButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { selectedDevice = (MediaDevice) deviceComboBox.getSelectedItem(); dispose(); } }); buttonsPanel.add(okButton); cancelButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { selectedDevice = null; dispose(); } }); buttonsPanel.add(cancelButton); return buttonsPanel; } /** * Create preview component. * * @param comboBox the options. * @return the component. */ private static Component createPreview(final JComboBox comboBox) { final JComponent preview; JLabel noPreview = new JLabel(GuiActivator.getResources().getI18NString("impl.media.configform.NO_PREVIEW")); noPreview.setHorizontalAlignment(SwingConstants.CENTER); noPreview.setVerticalAlignment(SwingConstants.CENTER); preview = createVideoContainer(noPreview); preview.setPreferredSize(new Dimension(WIDTH, 280)); preview.setMaximumSize(new Dimension(WIDTH, 280)); final ActionListener comboBoxListener = new ActionListener() { public void actionPerformed(ActionEvent event) { MediaDevice device = (MediaDevice) comboBox.getSelectedItem(); if ((device != null) && device.equals(videoDeviceInPreview)) return; Exception exception; try { createPreview(device, preview); exception = null; } catch (IOException ex) { exception = ex; } catch (MediaException ex) { exception = ex; } if (exception != null) { logger.error("Failed to create preview for device " + device, exception); device = null; } videoDeviceInPreview = device; } }; comboBox.addActionListener(comboBoxListener); /* * We have to initialize the controls to reflect the configuration * at the time of creating this instance. Additionally, because the * video preview will stop when it and its associated controls * become unnecessary, we have to restart it when the mentioned * controls become necessary again. We'll address the two goals * described by pretending there's a selection in the video combo * box when the combo box in question becomes displayable. */ comboBox.addHierarchyListener( new HierarchyListener() { public void hierarchyChanged(HierarchyEvent event) { if (((event.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) && comboBox.isDisplayable()) { // let current changes end their execution // and after that trigger action on combobox SwingUtilities.invokeLater( new Runnable() { public void run() { comboBoxListener.actionPerformed(null); } }); } else { if (!comboBox.isDisplayable()) videoDeviceInPreview = null; } } }); return preview; } /** * Creates preview for the device(video) in the video container. * * @param device the device * @param videoContainer the container * @throws IOException a problem accessing the device. * @throws MediaException a problem getting preview. */ private static void createPreview(MediaDevice device, final JComponent videoContainer) throws IOException, MediaException { videoContainer.removeAll(); videoContainer.revalidate(); videoContainer.repaint(); if (device == null) return; Component c = (Component) GuiActivator.getMediaService() .getVideoPreviewComponent( device, videoContainer.getSize().width, videoContainer.getSize().height); videoContainer.add(c); } /** * Creates the video container. * * @param noVideoComponent the container component. * @return the video container. */ private static JComponent createVideoContainer(Component noVideoComponent) { return new VideoContainer(noVideoComponent, false); } /** Custom combo box renderer. */ private static class ComboRenderer extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); MediaDevice mediaDevice = (MediaDevice) value; Dimension screenSize = null; if (mediaDevice != null) screenSize = ((VideoMediaFormat) mediaDevice.getFormat()).getSize(); this.setText(screenSize.width + "x" + screenSize.height); return this; } } /** * Automatically press the cancel button when this dialog has been escaped. * * @param escaped indicates if this dialog has been closed by pressing the ESC key */ @Override protected void close(boolean escaped) { if (escaped) cancelButton.doClick(); } }
/** * Create preview component. * * @param comboBox the options. * @return the component. */ private static Component createPreview(final JComboBox comboBox) { final JComponent preview; JLabel noPreview = new JLabel(GuiActivator.getResources().getI18NString("impl.media.configform.NO_PREVIEW")); noPreview.setHorizontalAlignment(SwingConstants.CENTER); noPreview.setVerticalAlignment(SwingConstants.CENTER); preview = createVideoContainer(noPreview); preview.setPreferredSize(new Dimension(WIDTH, 280)); preview.setMaximumSize(new Dimension(WIDTH, 280)); final ActionListener comboBoxListener = new ActionListener() { public void actionPerformed(ActionEvent event) { MediaDevice device = (MediaDevice) comboBox.getSelectedItem(); if ((device != null) && device.equals(videoDeviceInPreview)) return; Exception exception; try { createPreview(device, preview); exception = null; } catch (IOException ex) { exception = ex; } catch (MediaException ex) { exception = ex; } if (exception != null) { logger.error("Failed to create preview for device " + device, exception); device = null; } videoDeviceInPreview = device; } }; comboBox.addActionListener(comboBoxListener); /* * We have to initialize the controls to reflect the configuration * at the time of creating this instance. Additionally, because the * video preview will stop when it and its associated controls * become unnecessary, we have to restart it when the mentioned * controls become necessary again. We'll address the two goals * described by pretending there's a selection in the video combo * box when the combo box in question becomes displayable. */ comboBox.addHierarchyListener( new HierarchyListener() { public void hierarchyChanged(HierarchyEvent event) { if (((event.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) && comboBox.isDisplayable()) { // let current changes end their execution // and after that trigger action on combobox SwingUtilities.invokeLater( new Runnable() { public void run() { comboBoxListener.actionPerformed(null); } }); } else { if (!comboBox.isDisplayable()) videoDeviceInPreview = null; } } }); return preview; }