# HG changeset patch # User Jiri Vanek # Date 1447345160 -3600 # Node ID 104317f4809608d67b8dd6c6750ff40afebb2858 # Parent a27404e9786747a1da9179b5e508adde87de7628 Added desktop integration dialog diff -r a27404e97867 -r 104317f48096 ChangeLog --- a/ChangeLog Thu Nov 12 15:48:22 2015 +0100 +++ b/ChangeLog Thu Nov 12 17:19:20 2015 +0100 @@ -1,3 +1,29 @@ +2015-11-12 Jiri Vanek + + Added desktop integration dialog + * netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java: added linux-only + button to sow FreeDesktopIntegrationEditorFrame + * netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/Blinker.java: + new class, blink colors on selected component + * netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/FreeDesktopIntegrationEditorFrame.java: + new class, window to allow managing generated icons, jnlpfiles and shortcuts + * netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/JListUtils.java: + new class, provides models, extensions, renderers and listeners for FreeDesktopIntegrationEditorFrame + * netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/Panels.java: + new class, provides various encapsulated parts of FreeDesktopIntegrationEditorFrame + * netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/PreviewSelectionJTextPane.java: + new class, impelmetation of preview for FreeDesktopIntegrationEditorFrame + * netx/net/sourceforge/jnlp/resources/Messages.properties: added Control + Panel - desktop integration manager DIM family + * netx/net/sourceforge/jnlp/security/dialogs/SecurityDialogPanel.java: htmlWrap + made public + * netx/net/sourceforge/jnlp/util/XDesktopEntry.java: findFreedesktopOrgDesktopPathCatch + made public + * netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java: replacing of chars by html + entities extracted to new method escapeHtmlForJTextPane + * tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java: + htmlwrap moved to use SecurityDialogPanel's implementation + 2015-11-12 Jiri Vanek fixed build and runtime with jdk9 diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java --- a/netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java Thu Nov 12 15:48:22 2015 +0100 +++ b/netx/net/sourceforge/jnlp/controlpanel/DesktopShortcutPanel.java Thu Nov 12 17:19:20 2015 +0100 @@ -1,5 +1,5 @@ /* DesktopShortcutPanel.java -- Display option for adding desktop shortcut. -Copyright (C) 2010 Red Hat +Copyright (C) 2015 Red Hat This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,40 +15,42 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - package net.sourceforge.jnlp.controlpanel; import java.awt.Component; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.Box; +import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; +import javax.swing.SwingUtilities; import net.sourceforge.jnlp.ShortcutDesc; import net.sourceforge.jnlp.config.DeploymentConfiguration; +import net.sourceforge.jnlp.controlpanel.desktopintegrationeditor.FreeDesktopIntegrationEditorFrame; +import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.runtime.Translator; /** * This class provides the panel that allows the user to set whether they want * to create a desktop shortcut for javaws. - * - * @author Andrew Su (asu@redhat.com, andrew.su@utoronto.ca) - * */ public class DesktopShortcutPanel extends NamedBorderPanel implements ItemListener { private final DeploymentConfiguration config; + private FreeDesktopIntegrationEditorFrame integrationManagment; /** * Create a new instance of the desktop shortcut settings panel. - * - * @param config - * Loaded DeploymentConfiguration file. + * + * @param config Loaded DeploymentConfiguration file. */ public DesktopShortcutPanel(DeploymentConfiguration config) { super(Translator.R("CPHeadDesktopIntegration"), new GridBagLayout()); @@ -57,7 +59,6 @@ addComponents(); } - public static ComboItem deploymentJavawsShortcutToComboItem(String i) { return new ComboItem(ShortcutDesc.deploymentJavawsShortcutToString(i), i); } @@ -69,6 +70,27 @@ GridBagConstraints c = new GridBagConstraints(); JLabel description = new JLabel("" + Translator.R("CPDesktopIntegrationDescription") + "
"); JComboBox shortcutComboOptions = new JComboBox<>(); + JButton manageIntegrationsButton = new JButton(Translator.R("CPDesktopIntegrationShowIntegrations")); + if (JNLPRuntime.isWindows()) { + manageIntegrationsButton.setToolTipText(Translator.R("CPDesktopIntegrationLinuxOnly")); + manageIntegrationsButton.setEnabled(false); + } + manageIntegrationsButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + if (integrationManagment == null) { + integrationManagment = new FreeDesktopIntegrationEditorFrame(); + } + integrationManagment.setVisible(true); + } + }); + } + }); ComboItem[] items = {deploymentJavawsShortcutToComboItem(ShortcutDesc.CREATE_NEVER), deploymentJavawsShortcutToComboItem(ShortcutDesc.CREATE_ALWAYS), deploymentJavawsShortcutToComboItem(ShortcutDesc.CREATE_ASK_USER), @@ -92,6 +114,8 @@ add(description, c); c.gridy = 1; add(shortcutComboOptions, c); + c.gridy = 2; + add(manageIntegrationsButton, c); // This is to keep it from expanding vertically if resized. Component filler = Box.createRigidArea(new Dimension(1, 1)); diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/Blinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/Blinker.java Thu Nov 12 17:19:20 2015 +0100 @@ -0,0 +1,103 @@ +/* Copyright (C) 2015 Red Hat, Inc. + + This file is part of IcedTea. + + IcedTea is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + IcedTea is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with IcedTea; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + */ +package net.sourceforge.jnlp.controlpanel.desktopintegrationeditor; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.Timer; + +public class Blinker { + + private boolean blinking; + private final JComponent compToBlink; + + public Blinker(JComponent compToBlink) { + this.compToBlink = compToBlink; + } + + public void blink() { + if (blinking) { + return; + } + blinking = true; + Timer t = new Timer(100, new BlinkBody()); + t.setInitialDelay(0); + t.start(); + } + + class BlinkBody implements ActionListener { + + int counter = 0; + Color base; + Color invert; + + @Override + public void actionPerformed(ActionEvent e) { + counter++; + if (counter == 1) { + base = compToBlink.getBackground(); + invert = new Color(Math.min(255, base.getRed() * 2), Math.max(0, base.getGreen() / 2), 255 - base.getBlue()); + } + if (counter == 5) { + ((Timer) e.getSource()).stop(); + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + compToBlink.setBackground(base); + blinking = false; + } + }); + return; + } + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + if (compToBlink.getBackground().equals(base)) { + compToBlink.setBackground(invert); + } else { + compToBlink.setBackground(base); + } + } + }); + } + + } +} diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/FreeDesktopIntegrationEditorFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/FreeDesktopIntegrationEditorFrame.java Thu Nov 12 17:19:20 2015 +0100 @@ -0,0 +1,509 @@ +/* Copyright (C) 2015 Red Hat, Inc. + + This file is part of IcedTea. + + IcedTea is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + IcedTea is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with IcedTea; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + */ +package net.sourceforge.jnlp.controlpanel.desktopintegrationeditor; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextPane; +import javax.swing.ListModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import net.sourceforge.jnlp.config.PathsAndFiles; +import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel; +import net.sourceforge.jnlp.util.XDesktopEntry; +import net.sourceforge.jnlp.util.logging.ConsoleOutputPaneModel; + +import static net.sourceforge.jnlp.runtime.Translator.R; + +public class FreeDesktopIntegrationEditorFrame extends JFrame { + + //gui + private final javax.swing.JLabel title = new JLabel(); + private final javax.swing.JCheckBox selectRelativeRecordsFromOtherColumns = new JCheckBox(); + private final javax.swing.JButton removeSelectedButton = new JButton(); + private final javax.swing.JButton cleanAll = new JButton(); + private final javax.swing.JButton closeButton = new JButton(); + private final javax.swing.JButton reloadsListButton = new JButton(); + private final javax.swing.JButton selectAll = new JButton(); + + //important ones + private final javax.swing.JList menuList = new JListUtils.CustomRendererJList(); + private final javax.swing.JList desktopList = new JListUtils.CustomValidatingRendererJList(); + private final javax.swing.JList generatedList = new JListUtils.CustomRendererJList(); + private final javax.swing.JList iconsList = new JListUtils.CustomRendererWithIconJList(); + + PreviewSelectionJTextPane previewPane = new PreviewSelectionJTextPane(iconsList, menuList, desktopList, generatedList); + //gui end + + private final Blinker blinker; + + private void setListeners() { + removeSelectedButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + FreeDesktopIntegrationEditorFrame.this.removeSelected(); + } + }); + + closeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + dispose(); + } + }); + + reloadsListButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + populateLists(); + } + }); + + selectAll.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + selectAll(); + } + }); + + cleanAll.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cleanAll(); + } + }); + + } + + private void setTexts() { + this.setTitle(R("DIMtitle")); + closeButton.setText(R("ButClose")); + removeSelectedButton.setText(R("DIMremoveSelected")); + selectRelativeRecordsFromOtherColumns.setText(R("DIMselectRelativeRecordsFromOtherColumns")); + reloadsListButton.setText(R("DIMreloadLists")); + selectAll.setText(R("DIMselectAll")); + cleanAll.setText(R("DIMclearSelection")); + title.setText(SecurityDialogPanel.htmlWrap("

" + R("DIMdescription") + "

")); + } + + private JPanel createMainControls() { + JPanel mainControls = new JPanel(new GridLayout(1, 2)); + mainControls.add(closeButton); + mainControls.add(removeSelectedButton); + return mainControls; + } + + private JPanel createMiddleToolBox() { + JPanel middleToolBox = new JPanel(new GridLayout(1, 2)); + middleToolBox.add(selectRelativeRecordsFromOtherColumns); + middleToolBox.add(reloadsListButton); + middleToolBox.add(selectAll); + middleToolBox.add(cleanAll); + return middleToolBox; + } + + private JPanel createPreviewPanel(JTextPane previewPane) { + JPanel previewPanel = new JPanel(new BorderLayout()); + JScrollPane jScrollPane2 = new JScrollPane(); + jScrollPane2.setViewportView(previewPane); + previewPanel.add(jScrollPane2, BorderLayout.CENTER); + createMiddleToolBox(); + previewPanel.add(createMiddleToolBox(), BorderLayout.PAGE_START); + return previewPanel; + } + + private JSplitPane createListsLayout() { + JPanel menusPanel = Panels.createMenuPanel(menuList, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + selectSomeRelatives(menuList.getSelectedValuesList(), iconsList); + } + }, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + selectSomeRelatives(menuList.getSelectedValuesList(), generatedList); + } + } + ); + JPanel desktopsPanel = Panels.createDesktopPanel(desktopList, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + selectSomeRelatives(desktopList.getSelectedValuesList(), iconsList); + } + }, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + selectSomeRelatives(desktopList.getSelectedValuesList(), generatedList); + } + } + ); + JPanel iconsPanel = Panels.createIconsPanel(iconsList, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + findOrphans(iconsList, allItemsAsFiles(menuList), allItemsAsFiles(desktopList)); + } + }); + JPanel generatedsPanel = Panels.createGeneratedPanel(generatedList, new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + findOrphans(generatedList, allItemsAsFiles(menuList), allItemsAsFiles(desktopList)); + } + }); + return Panels.createQuadroSplit(expectedWidth, menusPanel, desktopsPanel, iconsPanel, generatedsPanel); + } + + private void setLayout() { + createMainControls(); + getContentPane().add(createMainControls(), BorderLayout.PAGE_END); + JSplitPane splitListsAndPreview = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + splitListsAndPreview.setLeftComponent(createListsLayout()); + splitListsAndPreview.setRightComponent(createPreviewPanel(previewPane)); + getContentPane().add(splitListsAndPreview, BorderLayout.CENTER); + getContentPane().add(title, BorderLayout.PAGE_START); + splitListsAndPreview.setDividerLocation(expectedHeight / 2); + } + + public static void main(String args[]) { + + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + new FreeDesktopIntegrationEditorFrame().setVisible(true); + } + }); + } + + private boolean selecting = false; + private final int expectedWidth = 800; + private final int expectedHeight = 600; + + public FreeDesktopIntegrationEditorFrame() { + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setSize(expectedWidth, expectedHeight); + populateLists(); + setTexts(); + setListeners(); + setLayout(); + selectRelativeRecordsFromOtherColumns.setSelected(true); + + ListSelectionListener generatePreviewListener = new GeneratePreviewListener(); + + iconsList.addListSelectionListener(generatePreviewListener); + desktopList.addListSelectionListener(generatePreviewListener); + menuList.addListSelectionListener(generatePreviewListener); + generatedList.addListSelectionListener(generatePreviewListener); + blinker = new Blinker(selectRelativeRecordsFromOtherColumns); + + } + + private void populateLists() { + menuList.setModel(new JListUtils.InfrastructureFileDescriptorListingBasedJListModel(PathsAndFiles.MENUS_DIR)); + desktopList.setModel(new JListUtils.FileListBasedJListModel(new File(XDesktopEntry.findFreedesktopOrgDesktopPathCatch()), "(?i)^.*\\.desktop$") { + + @Override + public String toString() { + return R("DIMguessedDesktop"); + } + }); + iconsList.setModel(new JListUtils.InfrastructureFileDescriptorListingBasedJListModel(PathsAndFiles.ICONS_DIR)); + generatedList.setModel(new JListUtils.InfrastructureFileDescriptorListingBasedJListModel(PathsAndFiles.GEN_JNLPS_DIR)); + } + + private void cleanAll() { + selecting = true; + try { + clearAll(); + } finally { + selecting = false; + } + } + + private void clearAll() { + desktopList.clearSelection(); + menuList.clearSelection(); + generatedList.clearSelection(); + iconsList.clearSelection(); + previewPane.setText(R("DIMselectionPreview")); + } + + private void removeSelected() { + int a = getTotal( + objectListToFileList(iconsList.getSelectedValuesList()), + objectListToFileList(menuList.getSelectedValuesList()), + objectListToFileList(desktopList.getSelectedValuesList()), + objectListToFileList(generatedList.getSelectedValuesList()) + ); + if (a <= 0) { + return; + } + int x = JOptionPane.showConfirmDialog(this, R("DIMaskBeforeDelete", a)); + if (x == JOptionPane.OK_OPTION || x == JOptionPane.YES_OPTION) { + removeSelected( + objectListToFileList(iconsList.getSelectedValuesList()), + objectListToFileList(menuList.getSelectedValuesList()), + objectListToFileList(desktopList.getSelectedValuesList()), + objectListToFileList(generatedList.getSelectedValuesList()) + ); + populateLists(); + } + } + + private void selectAll() { + selecting = true; + try { + selectAll(menuList); + selectAll(desktopList); + selectAll(iconsList); + selectAll(generatedList); + } finally { + selecting = false; + } + previewPane.generatePreview(); + } + + public List allItemsAsFiles(JList l) { + return allItemsAsFiles(l.getModel()); + } + + public List allItemsAsFiles(ListModel l) { + List r = new ArrayList<>(l.getSize()); + for (int i = 0; i < l.getSize(); i++) { + r.add((File) l.getElementAt(i)); + + } + return r; + } + + private List objectListToFileList(List l) { + List r = new ArrayList(l.size()); + for (Object l1 : l) { + r.add((File) l1); + } + return r; + } + + private void removeSelected(List... a) { + for (List list : a) { + for (File file : list) { + file.delete(); + + } + } + } + + private int getTotal(List... a) { + int i = 0; + for (List list : a) { + i+=list.size(); + } + return i; + } + + private void findOrphans(JList possibleOrphans, List... whereItCanBe) { + selecting = true; + if (selectRelativeRecordsFromOtherColumns.isSelected()) { + clearAll(); + blinker.blink(); + } + try { + possibleOrphans.clearSelection(); + List l = allItemsAsFiles(possibleOrphans); + for (int i = 0; i < l.size(); i++) { + File file = l.get(i); + boolean found = false; + for (List lf : whereItCanBe) { + if (found) { + break; + } + for (File f : lf) { + String s = fileToString(f, false); + if (s.contains(file.getAbsolutePath())) { + found = true; + break; + } + } + } + if (!found) { + possibleOrphans.addSelectionInterval(i, i); + } + } + } finally { + selecting = false; + } + previewPane.generatePreview(); + } + + private void selectSomeRelatives(List selected, JList target) { + selecting = true; + try { + selectFileFromShortcuts(selected, target); + } finally { + selecting = false; + } + previewPane.generatePreview(); + } + + private void selectAll(JList list) { + int start = 0; + int end = list.getModel().getSize() - 1; + if (end >= 0) { + list.setSelectionInterval(start, end); + } + } + + private class GeneratePreviewListener implements ListSelectionListener { + + public GeneratePreviewListener() { + } + + @Override + public void valueChanged(ListSelectionEvent e) { + if (selecting) { + return; + } + try { + selecting = true; + if (selectRelativeRecordsFromOtherColumns.isSelected()) { + blinker.blink(); + selectRelatives(e.getSource()); + + } + } finally { + selecting = false; + } + + previewPane.generatePreview(); + } + } + + private void selectRelatives(Object source) { + if (source instanceof JList) { + int[] indexes = ((JList) (source)).getSelectedIndices(); + clearAll(); + ((JList) (source)).setSelectedIndices(indexes); + } + + for (int x = 1; x <= 3; x++) { + //we dont wont recurse, so sending copies in + selectShortcutsByFiles( + objectListToFileList(iconsList.getSelectedValuesList()), + objectListToFileList(generatedList.getSelectedValuesList()) + ); + selectFilesByShortcuts( + objectListToFileList(menuList.getSelectedValuesList()), + objectListToFileList(desktopList.getSelectedValuesList()) + ); + } + } + + static String fileToString(File f, boolean escape) { + try (BufferedReader bufferedReader = new BufferedReader(new FileReader(f))) { + + StringBuilder sb = new StringBuilder(); + + while (true) { + String line = bufferedReader.readLine(); + if (line == null) { + return sb.toString(); + } + if (escape) { + line = ConsoleOutputPaneModel.escapeHtmlForJTextPane(line); + } + sb.append(line).append("\n"); + } + + } catch (Exception ex) { + return ex.toString(); + } + } + + private void selectShortcutsByFiles(List icons, List jnlps) { + selectShortcutsWithFiles(icons, desktopList); + selectShortcutsWithFiles(icons, menuList); + selectShortcutsWithFiles(jnlps, desktopList); + selectShortcutsWithFiles(jnlps, menuList); + } + + private void selectFilesByShortcuts(List menu, List desktop) { + selectFileFromShortcuts(desktop, iconsList); + selectFileFromShortcuts(desktop, generatedList); + selectFileFromShortcuts(menu, iconsList); + selectFileFromShortcuts(menu, generatedList); + } + + private void selectShortcutsWithFiles(List icons, JList list) { + for (int i = 0; i < list.getModel().getSize(); i++) { + File item = (File) list.getModel().getElementAt(i); + String s = fileToString(item, false); + for (File icon : icons) { + if (s.contains(icon.getAbsolutePath())) { + list.addSelectionInterval(i, i); + } + } + + } + } + + private void selectFileFromShortcuts(List shortcuts, JList files) { + for (File shortcut : shortcuts) { + String s = fileToString(shortcut, false); + for (int i = 0; i < files.getModel().getSize(); i++) { + File item = (File) files.getModel().getElementAt(i); + if (s.contains(item.getAbsolutePath())) { + files.addSelectionInterval(i, i); + } + + } + } + + } +} diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/JListUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/JListUtils.java Thu Nov 12 17:19:20 2015 +0100 @@ -0,0 +1,367 @@ +/* Copyright (C) 2015 Red Hat, Inc. + + This file is part of IcedTea. + + IcedTea is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + IcedTea is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with IcedTea; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + */ +package net.sourceforge.jnlp.controlpanel.desktopintegrationeditor; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import javax.imageio.ImageIO; +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JList; + +import javax.swing.ListModel; +import javax.swing.event.ListDataListener; +import net.sourceforge.jnlp.config.InfrastructureFileDescriptor; +import net.sourceforge.jnlp.util.XDesktopEntry; + +public class JListUtils { + + private static Map iconCache = new HashMap<>(); + private static Map textFilesCache = new HashMap<>(); + private static Map stamps = new HashMap<>(); + + public static class InfrastructureFileDescriptorListingBasedJListModel extends FileListBasedJListModel { + + private final InfrastructureFileDescriptor source; + + public InfrastructureFileDescriptorListingBasedJListModel(InfrastructureFileDescriptor source, String mask) { + super(source.getFile(), mask); + this.source = source; + } + + public InfrastructureFileDescriptorListingBasedJListModel(InfrastructureFileDescriptor source) { + super(source.getFile()); + this.source = source; + } + + public InfrastructureFileDescriptor getSource() { + return source; + } + + @Override + protected File getFile() { + return source.getFile(); + } + + @Override + public String toString() { + return source.toString(); + } + + } + + public static class FileListBasedJListModel implements ListModel { + + private final File directory; + private File[] list; + private final Pattern mask; + + /** + * Construct list containing all files from given directory + * + * @param dir + */ + public FileListBasedJListModel(File dir) { + //calling constructor with regex matching every file + this(dir, ".*"); + } + + /** + * Construct list containing files from given directory matching regex of given mask, + * + * @param dir directory to list + * @param mask regex to match files to display + */ + public FileListBasedJListModel(File dir, final String mask) { + directory = dir; + this.mask = Pattern.compile(mask); + } + + protected File getFile() { + return directory; + } + + @Override + public String toString() { + return getFile().getAbsolutePath(); + } + + private File[] populateList() { + list = getFile().listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return mask.matcher(name).matches(); + } + }); + return list; + } + + @Override + public int getSize() { + if (list == null) { + populateList(); + } + return list.length; + } + + @Override + public Object getElementAt(int index) { + if (list == null) { + populateList(); + } + return list[index]; + } + + @Override + public void addListDataListener(ListDataListener l) { + + } + + @Override + public void removeListDataListener(ListDataListener l) { + + } + + } + + public static class CustomRendererJList extends JList { + + public CustomRendererJList() { + this.setCellRenderer(new FileCellRenderer()); + } + + } + + public static class CustomValidatingRendererJList extends JList { + + public CustomValidatingRendererJList() { + this.setCellRenderer(new ValidatingFileCellRenderer()); + } + + } + + public static class CustomRendererWithIconJList extends JList { + + public CustomRendererWithIconJList() { + setCellRenderer(new IconisedCellRenderer()); + } + + } + + private static class FileCellRenderer extends DefaultListCellRenderer { + + @Override + public Component getListCellRendererComponent( + JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + + File f = (File) value; + JLabel label = (JLabel) super.getListCellRendererComponent( + list, value, index, isSelected, cellHasFocus); + label.setText(f.getName()); + return label; + } + } + + private static class ValidatingFileCellRenderer extends FileCellRenderer { + + @Override + public Component getListCellRendererComponent( + JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + File f = (File) value; + String s = processTextFilesCache(f); + if (!isSelected) { + if (isJavaws(s)) { + l.setBackground(new Color(0, 200, 0)); + + } else if (isBrowser(s)) { + l.setBackground(new Color(100, 150, 0)); + } else { + l.setBackground(new Color(255, 200, 200)); + } + } else { + if (isJavaws(s)) { + l.setForeground(new Color(0, 200, 0)); + + } else if (isBrowser(s)) { + l.setForeground(new Color(100, 150, 0)); + } else { + l.setForeground(new Color(255, 200, 200)); + } + } + return l; + } + + private boolean isJavaws(String s) { + return haveString(s, "javaws"); + } + + private boolean isBrowser(String s) { + String[] browsers = XDesktopEntry.BROWSERS; + for (String browser : browsers) { + if (haveString(s, browser)) { + return true; + } + } + return false; + } + + private boolean haveString(String s, String i) { + return s.matches("(?sm).*^.*Exec.*=.*" + i + ".*$.*"); + } + } + + private static class IconisedCellRenderer extends DefaultListCellRenderer { + + @Override + public Component getListCellRendererComponent( + JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + + File f = (File) value; + JLabel label = (JLabel) super.getListCellRendererComponent( + list, value, index, isSelected, cellHasFocus); + label.setIcon(processIconCache(f)); + label.setText(f.getName()); + label.setHorizontalTextPosition(JLabel.RIGHT); + return label; + } + + } + + /** + * This method looks to cache whether file F was already read as image. + * If not, file is loaded, put to cache and returned + * If so, it also check whether it was modified. If so, it is reloaded, replaced in cache and returned. + * + * @param f + * @return + */ + private static Icon processIconCache(File f) { + Icon i = iconCache.get(f); + if (i == null) { + i = updateIconCache(f, i); + } else { + if (f.lastModified() != stamps.get(f)) { + i = updateIconCache(f, i); + } + } + return i; + } + + /** + * This method load Icon from file. + * Once file is loaded, it is stored also to cache + * Also the time stamp of last modification is stored to cache to allow reloading when changed. + * + * @param f file to load, and to provide timestamp of last modification + * @return loaded icon or null + */ + private static Icon updateIconCache(File f, Icon i) { + i = createImageIcon(f, f.getAbsolutePath()); + if (i != null) { + iconCache.put(f, i); + stamps.put(f, f.lastModified()); + } + return i; + } + + /** + * This method looks to cache whether file F was already read as text file. + * If not, file is loaded, and its content is put to cache and returned as String + * If so, it also check whether it was modified. If so, it is reloaded, replaced in cache and returned. + * + * @param f + * @return + */ + private static String processTextFilesCache(File f) { + String s = textFilesCache.get(f); + if (s == null) { + s = updateTextCache(f, s); + } else { + if (f.lastModified() != stamps.get(f)) { + s = updateTextCache(f, s); + } + } + return s; + } + + /** + * This method load Text from file. + * Once file is loaded, it is stored also to cache + * Also the time stamp of last modification is stored to cache to allow reloading when changed. + * + * @param f file to load, and to provide timestamp of last modification + * @return loaded Text, error message or null + */ + private static String updateTextCache(File f, String s) { + s = FreeDesktopIntegrationEditorFrame.fileToString(f, false); + if (s != null) { + textFilesCache.put(f, s); + stamps.put(f, f.lastModified()); + } + return s; + } + + /** + * Load BufferedImage form file, scale it and converts to icon. + * + * @param f file to be loaded + * @param description description to be provided + * @return icon from file or null if something went wrong + */ + private static ImageIcon createImageIcon(File f, String description) { + try { + BufferedImage i = ImageIO.read(f); + return new ImageIcon(i.getScaledInstance(50, 50, Image.SCALE_SMOOTH)); + } catch (Exception ex) { + //not worthy to log it. No image is there and so be it. + return null; + } + } +} diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/Panels.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/Panels.java Thu Nov 12 17:19:20 2015 +0100 @@ -0,0 +1,152 @@ +/* Copyright (C) 2015 Red Hat, Inc. + + This file is part of IcedTea. + + IcedTea is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + IcedTea is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with IcedTea; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + */ +package net.sourceforge.jnlp.controlpanel.desktopintegrationeditor; + +import java.awt.BorderLayout; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel; + +import static net.sourceforge.jnlp.runtime.Translator.R; + +public class Panels { + + public static JPanel createGeneratedPanel(JList list, ActionListener findOrphans) { + return createIconsOrGeneratedPanel(list, findOrphans, R("DIMgeneratedJnlps"), bold(R("DIMgeneratedJnlpsTooltip"))); + } + + public static JPanel createIconsPanel(JList list, ActionListener findOrphans) { + return createIconsOrGeneratedPanel(list, findOrphans, R("DIMicons"), bold(R("DIMiconsTooltip"))); + } + + private static JPanel createIconsOrGeneratedPanel(JList list, ActionListener findOrphans, String title, String tooltip) { + JPanel iconsPanel = new JPanel(new BorderLayout()); + JLabel l = new JLabel(title); + l.setToolTipText(createToolTip(tooltip, list)); + iconsPanel.add(l, BorderLayout.PAGE_START); + JScrollPane scrollIcons = new JScrollPane(); + scrollIcons.setViewportView(list); + iconsPanel.add(scrollIcons, BorderLayout.CENTER); + JPanel iconsToolPanel = new JPanel(new BorderLayout()); + JButton findOrphansButton = new JButton(R("DIMorphans")); + findOrphansButton.addActionListener(findOrphans); + findOrphansButton.setToolTipText(R("DIMorphansTooltip")); + iconsToolPanel.add(findOrphansButton, BorderLayout.CENTER); + iconsPanel.add(iconsToolPanel, BorderLayout.PAGE_END); + return iconsPanel; + } + + public static JPanel createMenuPanel(JList list, ActionListener findIcons, ActionListener findGenerated) { + return createDesktopOrMenuPanel(list, findIcons, findGenerated, R("DIMmenuItems"), bold(R("DIMmenuItemsTooltip"))); + } + + public static JPanel createDesktopPanel(JList list, ActionListener findIcons, ActionListener findGenerated) { + StringBuilder sb = new StringBuilder(); + sb.append(R("DIMdesktopItemsTooltipL1")).append("
") + .append(R("DIMdesktopItemsTooltipL2")).append(":" + "
    " + "
  • ") + .append(R("DIMdesktopItemsTooltipL3")).append("
  • " + "
  • ") + .append(R("DIMdesktopItemsTooltipL4")).append("
  • " + "
  • ") + .append(R("DIMdesktopItemsTooltipL5")).append("
  • " + "
") + .append(bold(R("DIMdesktopItemsTooltipL6"))); + return createDesktopOrMenuPanel(list, findIcons, findGenerated, R("DIMdesktopItems"), sb.toString()); + } + + private static JPanel createDesktopOrMenuPanel(JList list, ActionListener findIcons, ActionListener findGenerated, String title, String tooltip) { + JPanel desktopPanel = new JPanel(new BorderLayout()); + JLabel l = new JLabel(title); + l.setToolTipText(createToolTip(tooltip, list)); + desktopPanel.add(l, BorderLayout.PAGE_START); + JScrollPane scrollDesktop = new JScrollPane(); + scrollDesktop.setViewportView(list); + desktopPanel.add(scrollDesktop, BorderLayout.CENTER); + JPanel desktopToolPanel = createDesktopOrMenuToolBox(findIcons, findGenerated); + desktopPanel.add(desktopToolPanel, BorderLayout.PAGE_END); + return desktopPanel; + } + + private static String createToolTip(String tooltip, JList list) { + if (tooltip != null) { + JListUtils.FileListBasedJListModel model = (JListUtils.FileListBasedJListModel) (list.getModel()); + StringBuilder sb = new StringBuilder(); + sb.append("
  • ") + .append(model.getFile()).append("

  • " + "
  • ") + .append(model.toString()).append("

  • " + "
  • ") + .append(tooltip).append("
"); + String tt = SecurityDialogPanel.htmlWrap(sb.toString()); + return tt; + } + return null; + } + + private static JPanel createDesktopOrMenuToolBox(ActionListener findIcons, ActionListener findGenerated) { + JPanel desktopToolPanel = new JPanel(new BorderLayout()); + JButton desktopFindGeneratedButton = new JButton(R("DIMgeneratedButton")); + desktopFindGeneratedButton.setToolTipText(R("DIMgeneratedButtonTooltip")); + desktopFindGeneratedButton.addActionListener(findGenerated); + JButton desktopFindIconsButton = new JButton(R("DIMiconsButton")); + desktopFindIconsButton.setToolTipText(R("DIMiconsButtonTooltip")); + desktopFindIconsButton.addActionListener(findIcons); + desktopToolPanel.add(desktopFindGeneratedButton, BorderLayout.LINE_END); + desktopToolPanel.add(desktopFindIconsButton, BorderLayout.LINE_START); + return desktopToolPanel; + } + + static JSplitPane createQuadroSplit(int width, JPanel menusPanel, JPanel desktopsPanel, JPanel iconsPanel, JPanel generatedsPanel) { + JSplitPane splitAllAndGenerated = new JSplitPane(); + JSplitPane splitIconsAndLists = new JSplitPane(); + JSplitPane splitLists = new JSplitPane(); + splitLists.setLeftComponent(menusPanel); + splitLists.setRightComponent(desktopsPanel); + splitIconsAndLists.setRightComponent(splitLists); + splitIconsAndLists.setLeftComponent(iconsPanel); + splitAllAndGenerated.setLeftComponent(splitIconsAndLists); + splitAllAndGenerated.setRightComponent(generatedsPanel); + splitAllAndGenerated.setDividerLocation(width / 5 * 4); + splitIconsAndLists.setDividerLocation(width / 4); + splitLists.setDividerLocation(width / 4); + return splitAllAndGenerated; + } + + private static String bold(String s) { + return "" + s + ""; + } + +} diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/PreviewSelectionJTextPane.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netx/net/sourceforge/jnlp/controlpanel/desktopintegrationeditor/PreviewSelectionJTextPane.java Thu Nov 12 17:19:20 2015 +0100 @@ -0,0 +1,155 @@ +/* Copyright (C) 2015 Red Hat, Inc. + + This file is part of IcedTea. + + IcedTea is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + IcedTea is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with IcedTea; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + + Linking this library statically or dynamically with other modules is + making a combined work based on this library. Thus, the terms and + conditions of the GNU General Public License cover the whole + combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent + modules, and to copy and distribute the resulting executable under + terms of your choice, provided that you also meet, for each linked + independent module, the terms and conditions of the license of that + module. An independent module is a module which is not derived from + or based on this library. If you modify this library, you may extend + this exception to your version of the library, but you are not + obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + */ +package net.sourceforge.jnlp.controlpanel.desktopintegrationeditor; + +import java.io.File; +import java.util.List; +import javax.swing.JList; +import javax.swing.JTextPane; +import javax.swing.text.html.HTMLEditorKit; +import net.sourceforge.jnlp.util.logging.OutputController; + +import static net.sourceforge.jnlp.runtime.Translator.R; + +public class PreviewSelectionJTextPane extends JTextPane { + + private final JList iconsList; + private final JList menuList; + private final JList desktopList; + private final JList generatedList; + + public PreviewSelectionJTextPane(JList iconsList, JList menuList, JList desktopList, JList generatedList) { + this.iconsList = iconsList; + this.menuList = menuList; + this.desktopList = desktopList; + this.generatedList = generatedList; + this.setEditorKit(new HTMLEditorKit()); + this.setEditable(false); + } + + private StringBuilder getMenus() { + return getTextFiles(menuList.getSelectedValuesList()); + } + + private StringBuilder getDesktops() { + return getTextFiles(desktopList.getSelectedValuesList()); + } + + private StringBuilder getGenerated() { + return getTextFiles(generatedList.getSelectedValuesList()); + } + + private StringBuilder getHeader(boolean i, boolean d, boolean m, boolean g) { + StringBuilder sb = new StringBuilder(); + if (i || d || m || g) { + sb.append(""); + } + if (i) { + sb.append("").append(R("DIMicons")).append(":"); + } + if (d) { + sb.append("").append(R("DIMdesktopItems")).append(":"); + } + if (m) { + sb.append("").append(R("DIMmenuItems")).append(":"); + } + if (g) { + sb.append("").append(R("DIMgeneratedJnlps")).append(":"); + } + + if (i || d || m || g) { + sb.append(""); + } + return sb; + } + + public void generatePreview() { + try { + StringBuilder sb = new StringBuilder(""); + sb.append(getHeader(iconsList.getSelectedIndices().length > 0, + menuList.getSelectedIndices().length > 0, + desktopList.getSelectedIndices().length > 0, + generatedList.getSelectedIndices().length > 0)).append(""); + if (iconsList.getSelectedIndices().length > 0) { + sb.append(""); + } + if (menuList.getSelectedIndices().length > 0) { + sb.append(""); + } + if (desktopList.getSelectedIndices().length > 0) { + sb.append(""); + } + if (generatedList.getSelectedIndices().length > 0) { + sb.append(""); + } + sb.append("
").append(getIcons()).append("").append(getMenus()).append("").append(getDesktops()).append("").append(getGenerated()).append("
"); + this.setText(sb.toString()); + + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + + } + + private StringBuilder getIcons() { + StringBuilder s = new StringBuilder(); + try { + List l = iconsList.getSelectedValuesList(); + for (Object l1 : l) { + File f = (File) l1; + s.append("").append(f.getAbsolutePath()).append("
"); + s.append("
"); + + } + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + return s; + } + + private StringBuilder getTextFiles(List selectedValuesList) { + StringBuilder s = new StringBuilder(); + for (Object i : selectedValuesList) { + File f = (File) i; + s.append("").append(f.getAbsolutePath()).append("
"); + s.append("
").append(FreeDesktopIntegrationEditorFrame.fileToString(f, true)).append("

"); + + } + return s; + + } + +} diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/resources/Messages.properties --- a/netx/net/sourceforge/jnlp/resources/Messages.properties Thu Nov 12 15:48:22 2015 +0100 +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties Thu Nov 12 17:19:20 2015 +0100 @@ -559,6 +559,8 @@ CPSecurityDescription=Use this to configure security settings. CPDebuggingDescription=Enable options here to help with debugging CPDesktopIntegrationDescription=Set whether or not to allow creation of desktop shortcut. +CPDesktopIntegrationShowIntegrations=Show desktop and menu integrations window +CPDesktopIntegrationLinuxOnly=Desktop integration manager available only for Linux. Sorry CPJVMPluginArguments=Set JVM arguments for plugin. CPJVMitwExec=Set JVM for IcedTea-Web \u2014 working best with OpenJDK CPJVMitwExecValidation=Validate JVM for IcedTea-Web @@ -971,6 +973,37 @@ CVCPColPath=Path CVCPColName=Name +# Control Panel - desktop integration manager +DIMtitle=IcedTea-Web Shortcut Manager +DIMremoveSelected=Remove selected +DIMselectRelativeRecordsFromOtherColumns=Select related records +DIMreloadLists=Reload +DIMselectAll=Select all +DIMclearSelection=Deselect all +DIMdescription=Manage the shorctuts and resources (cached images, etc) IcedTea-Web created for desktop integration +DIMguessedDesktop=Desktop folder as well guessed as possible. +DIMselectionPreview=Selection preview +DIMaskBeforeDelete=Are you sure you want to delete {0} files? +DIMgeneratedJnlps=Generated JNLPs +DIMgeneratedJnlpsTooltip=All files in this list should be generated by IcedTea-Web! +DIMicons=Icons +DIMiconsTooltip=All files in this list should be icons cached by IcedTea-Web! +DIMorphans=orphans +DIMorphansTooltip=Will select all items which are not listed in any shortcut. +DIMmenuItems=Menu Items +DIMmenuItemsTooltip=All shortcuts in this list should be generated by IcedTea-Web! +DIMdesktopItems=Desktop Items +DIMdesktopItemsTooltipL1=Not all your shortcuts on your Desktop were generated by IcedTea-Web! +DIMdesktopItemsTooltipL2=For your convenience: +DIMdesktopItemsTooltipL3=red items were probably not generated by IcedTea-Web +DIMdesktopItemsTooltipL4=dark green items are browser shortcuts, so they were probably generated by IcedTea-Web +DIMdesktopItemsTooltipL5=green items are javaws shortcuts, so they were very likely generated by IcedTea-Web +DIMdesktopItemsTooltipL6=In all cases, be careful what you delete, and verify connections with `select related records` mode +DIMgeneratedButton=generated +DIMgeneratedButtonTooltip=Will select related generated stuff. +DIMiconsButton=icons +DIMiconsButtonTooltip=Will select related cached icons. + # Control Panel - Misc. CPJRESupport=IcedTea-Web currently does not support the use of multiple JREs. CPInvalidPort=Invalid port number given.\n[Valid port numbers are 1-65535] diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/security/dialogs/SecurityDialogPanel.java --- a/netx/net/sourceforge/jnlp/security/dialogs/SecurityDialogPanel.java Thu Nov 12 15:48:22 2015 +0100 +++ b/netx/net/sourceforge/jnlp/security/dialogs/SecurityDialogPanel.java Thu Nov 12 17:19:20 2015 +0100 @@ -71,7 +71,7 @@ /** * Needed to get word wrap working in JLabels. */ - protected String htmlWrap(String s) { + public static String htmlWrap(String s) { return "" + s + ""; } diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/util/XDesktopEntry.java --- a/netx/net/sourceforge/jnlp/util/XDesktopEntry.java Thu Nov 12 15:48:22 2015 +0100 +++ b/netx/net/sourceforge/jnlp/util/XDesktopEntry.java Thu Nov 12 17:19:20 2015 +0100 @@ -531,7 +531,7 @@ return fPath; } - private static String findFreedesktopOrgDesktopPathCatch() { + public static String findFreedesktopOrgDesktopPathCatch() { try { return findFreedesktopOrgDesktopPath(); } catch (Exception ex) { diff -r a27404e97867 -r 104317f48096 netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java --- a/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java Thu Nov 12 15:48:22 2015 +0100 +++ b/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java Thu Nov 12 17:19:20 2015 +0100 @@ -205,11 +205,7 @@ } String line = (createLine(messageWithHeader)); if (mark) { - line = line.replaceAll("<", "<"); - line = line.replaceAll(">", ">"); - line = line.replaceAll("\n", "
\n"); - line = line.replaceAll(" ", "  ");//small trick, html is reducting row of spaces to single space. This handles it and stimm allow line wrap - line = line.replaceAll("\t", "    "); + line = escapeHtmlForJTextPane(line); } sb.append(line); if (mark) { @@ -229,6 +225,15 @@ } + public static String escapeHtmlForJTextPane(String line) { + line = line.replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll("\n", "
\n") + .replaceAll(" ", "  ")//small trick, html is reducting row of spaces to single space. This handles it and stimm allow line wrap + .replaceAll("\t", "    "); + return line; + } + String createLine(MessageWithHeader m) { StringBuilder sb = new StringBuilder(); if (showHeaders) { diff -r a27404e97867 -r 104317f48096 tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java --- a/tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java Thu Nov 12 15:48:22 2015 +0100 +++ b/tests/netx/unit/net/sourceforge/jnlp/security/dialogs/apptrustwarningpanel/AppTrustWarningPanelTest.java Thu Nov 12 17:19:20 2015 +0100 @@ -14,6 +14,7 @@ import net.sourceforge.jnlp.PluginParameters; import net.sourceforge.jnlp.browsertesting.browsers.firefox.FirefoxProfilesOperator; import net.sourceforge.jnlp.config.PathsAndFiles; +import net.sourceforge.jnlp.security.dialogs.SecurityDialogPanel; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -138,7 +139,7 @@ public void testHtmlWrap() throws Exception { final String testText = "This is some text"; final String expectedResult = "This is some text"; - final String actualResult = UnsignedAppletTrustWarningPanel.htmlWrap(testText); + final String actualResult = SecurityDialogPanel.htmlWrap(testText); assertEquals("htmlWrap should properly wrap text with HTML tags", expectedResult, actualResult); }