package fr.tikione.steam.cleaner.gui.dialog; import fr.tikione.ini.InfinitiveLoopException; import fr.tikione.ini.util.StringHelper; import fr.tikione.steam.cleaner.Version; import fr.tikione.steam.cleaner.util.FileComparator; import fr.tikione.steam.cleaner.util.FileUtils; import fr.tikione.steam.cleaner.util.GraphicsUtils; import fr.tikione.steam.cleaner.util.Log; import fr.tikione.steam.cleaner.util.Redist; import fr.tikione.steam.cleaner.util.RedistTableModel; import fr.tikione.steam.cleaner.util.Translation; import fr.tikione.steam.cleaner.util.UpdateManager; import fr.tikione.steam.cleaner.util.conf.Config; import fr.tikione.steam.cleaner.util.conf.CustomFolders; import fr.tikione.steam.cleaner.util.conf.DangerousItems; import fr.tikione.steam.cleaner.util.conf.Patterns; import fr.tikione.steam.cleaner.util.conf.UncheckedItems; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowStateListener; import java.io.CharConversionException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.GroupLayout; import javax.swing.GroupLayout.Alignment; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.ListSelectionModel; import javax.swing.RowSorter; import javax.swing.SwingConstants; import javax.swing.WindowConstants; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; /** * Main window. */ @SuppressWarnings("serial") public class JFrameMain extends JFrame { /** Indicate if the application in exiting. */ private static boolean CLOSING_APP = false; /** Initial label of the Reload button. */ private String btnReloadLabelInitial; /** Label of the Reload button when application is searching for redistributable packages. */ private String btnReloadLabelWorking; /** Initial label of the table that contains list of redistributable packages found. */ private String tblRedistLabelDefault; /** Default table model for the list of redistributable packages found. */ private DefaultTableModel model; private final DefaultListModel<File> listModel; /** List of non-checked items in the list of redistributable packages. */ private List<String> uncheckedRedistPathList = new ArrayList<>(8); /** Application configuration handler. */ private final Config config; /** The program configuration handler (redist patterns). */ private final Patterns patternsCfg; /** Application configuration handler. */ private final UncheckedItems uncheckedItems; /** Application configuration handler. */ private final CustomFolders customFolders; /** Application configuration handler. */ private final DangerousItems dangerousItems; /** List of folders patterns to exclude from the search path. */ private final List<Pattern> dangerousFolders; /** Steam directory. */ private File fSteamDir = null; /** Translated application's messages handler. */ private final Translation translation; /** * Create new form JFrameMain. This is the main form. * * @throws IOException if an error occurs while loading configuration file. * @throws CharConversionException if an error occurs while loading configuration file. * @throws InfinitiveLoopException if an error occurs while loading configuration file. */ @SuppressWarnings({"LeakingThisInConstructor", "unchecked", "OverridableMethodCallInConstructor"}) public JFrameMain() throws IOException, CharConversionException, InfinitiveLoopException { super(); GraphicsUtils.setIcon(this); config = Config.getInstance(); patternsCfg = Patterns.getInstance(); dangerousItems = DangerousItems.getInstance(); dangerousFolders = dangerousItems.getDangerousFolders(); String lngCode = config.getSelectedLanguage(); translation = new Translation(lngCode); model = new RedistTableModel(translation); // Model for the (visual) list a detected redistributable packages. initComponents(); secondInitComponents(translation); setTitle("TikiOne Steam Cleaner"); if (config.getCheckForUpdatesAtStartup()) { checkForUpdates(); } jLabelAppVersion.setText(' ' + translation.getString(Translation.SEC_WMAIN, "version.title").replace( "{0}", Version.VERSION) + ' '); // Restore latest frame state and center it. if (config.getUIState() == JFrame.MAXIMIZED_BOTH) { setExtendedState(config.getUIState()); } else { setSize(config.getUILatestWidth(), config.getUILatestHeight()); } GraphicsUtils.setFrameCentered(this); // Restore latest saved steam directory. Try to detect it if no steam directory previously found (or first run). String latestSteamDirStr = config.getLatestSteamFolder(); if (latestSteamDirStr.length() > 0) { File possibleSteamDir = new File(latestSteamDirStr); fSteamDir = possibleSteamDir; jTextFieldSteamDir.setText(fSteamDir.getAbsolutePath()); } else { locateSteamDir(); } uncheckedItems = new UncheckedItems(); uncheckedRedistPathList.addAll(uncheckedItems.getUncheckedItems()); setTableModelUI(); listModel = new DefaultListModel<>(); jListCustomFolders.setModel(listModel); customFolders = new CustomFolders(); List<String> customFoldersAsStr = customFolders.getCustomFolders(); customFoldersAsStr.stream().forEach((foldername) -> { listModel.addElement(new File(foldername)); }); jButtonReloadRedistList.setEnabled(true); } /** * Additional components initialization : translate messages and titles, and make some custom UI transformations. * * @param translation the program language translation handler. */ private void secondInitComponents(Translation translation) { btnReloadLabelInitial = translation.getString(Translation.SEC_WMAIN, "button.search"); btnReloadLabelWorking = translation.getString(Translation.SEC_WMAIN, "button.search.working"); tblRedistLabelDefault = translation.getString(Translation.SEC_WMAIN, "redistList.title"); jButtonLocateSteamDir.setText(translation.getString(Translation.SEC_WMAIN, "button.locateSteam")); jButtonManualSteamDirSearch.setText(translation.getString(Translation.SEC_WMAIN, "button.locateSteamManually")); jButtonReloadRedistList.setText(btnReloadLabelInitial); jButtonRemoveRedistItemsFromDisk.setText(translation.getString(Translation.SEC_WMAIN, "button.removeSelectedItems")); jLabelSteamDir.setText(translation.getString(Translation.SEC_WMAIN, "label.steamDir")); jButtonToolbarOptions.setToolTipText(translation.getString(Translation.SEC_WMAIN, "menu.options")); jButtonToolbarCheckforupdates.setToolTipText(translation.getString(Translation.SEC_WMAIN, "menu.checkForUpdates")); jButtonToolbarAbout.setToolTipText(translation.getString(Translation.SEC_WMAIN, "menu.about")); jPanelList.setBorder(BorderFactory.createTitledBorder(tblRedistLabelDefault)); jButtonAddCustomFolder.setText(translation.getString(Translation.SEC_WMAIN, "button.add.custom.folder")); jButtonRemoveCustomFolder.setText(translation.getString(Translation.SEC_WMAIN, "button.rem.custom.folder")); jLabelCustomFolders.setText("<html>" + translation.getString(Translation.SEC_WMAIN, "label.custom.folders.list") + "</html>"); jButtonStopSearch.setVisible(false); jButtonGithub.setToolTipText("<html><body>" + "TikiOne <b>GitHub</b>" + "<br><font color=\"blue\">https://github.com/jonathanlermitage/tikione-steam-cleaner</font></body></html>"); jButtonTwitter.setToolTipText("<html><body>" + "TikiOne <b>Twitter</b>" + "<br><font color=\"blue\">https://twitter.com/JLermitage</font></body></html>"); } /** * Get an array of File objetcs from the list of custom folders. * * @return an array of folders. */ private File[] customFoldersListStrToFiles() { int nbFolders = listModel.size(); List<File> folders = new ArrayList<>(nbFolders + 1); for (int i = 0; i < nbFolders; i++) { folders.add(listModel.get(i)); } return folders.toArray(new File[folders.size()]); } /** * Save the list of custom folders to a configuration file. */ private void memorizeCustomFoldersToConf() { try { File[] folders = customFoldersListStrToFiles(); List<String> foldersAsStr = new ArrayList<>(folders.length + 1); for (File folder : folders) { foldersAsStr.add(folder.getAbsolutePath()); } customFolders.setCustomFolders(foldersAsStr); } catch (CharConversionException | InfinitiveLoopException ex) { Log.error(ex); } } private void recomputeTotalSizeMB() { float fsize = 0; for (int i = 0; i < model.getRowCount(); i++) { if (Boolean.parseBoolean(model.getValueAt(i, 0).toString())) { fsize += Float.parseFloat(model.getValueAt(i, 2).toString()); } } String btnLabel = translation.getString(Translation.SEC_WMAIN, "button.removeSelectedItems"); jButtonRemoveRedistItemsFromDisk.setText(btnLabel + " (" + (int)fsize + "MB)"); } /** * Store the list of unchecked items (redistributable packages shown in the main table) to a configuration file. */ private void memorizeUncheckedItemsToConf() { try { if (fSteamDir != null) { List<String> nowUncheckedItemsList = new ArrayList<>(8); List<String> nowCheckedItemsList = new ArrayList<>(8); List<String> newUncheckedItemsList = new ArrayList<>(8); List<String> prevUncheckedItems = uncheckedItems.getUncheckedItems(); for (int row = 0; row < model.getRowCount(); row++) { boolean checked = (Boolean) model.getValueAt(row, 0); String redistFullPath = (String) model.getValueAt(row, 1); if (checked) { nowCheckedItemsList.add(redistFullPath); } else { nowUncheckedItemsList.add(redistFullPath); } } newUncheckedItemsList.addAll(nowUncheckedItemsList); for (String prevUncheckedItem : prevUncheckedItems) { if (!nowCheckedItemsList.contains(prevUncheckedItem) && !newUncheckedItemsList.contains(prevUncheckedItem)) { newUncheckedItemsList.add(prevUncheckedItem); } } uncheckedItems.setUncheckedItems(newUncheckedItemsList); } } catch (CharConversionException | InfinitiveLoopException ex) { Log.error(ex); } } private void searchRedistPackagesOnDisk(final JButton buttonReload) { buttonReload.setEnabled(false); memorizeUncheckedItemsToConf(); jPanelList.setBorder(BorderFactory.createTitledBorder(tblRedistLabelDefault)); String sSteamDir = jTextFieldSteamDir.getText(); if (!listModel.isEmpty() || !StringHelper.strIsEmpty(sSteamDir)) { if (!StringHelper.strIsEmpty(sSteamDir) && !sSteamDir.endsWith("/") && !sSteamDir.endsWith(File.separator)) { sSteamDir += File.separatorChar; } fSteamDir = new File(sSteamDir); boolean steamExists = fSteamDir.isDirectory() && fSteamDir.exists(); if (!listModel.isEmpty() || steamExists) { enableAllUI(false); buttonReload.setText(btnReloadLabelWorking); final JFrame thisframe = this; Thread tJob = new Thread(() -> { try { jButtonStopSearch.setVisible(true); String nameFile = translation.getString(Translation.SEC_WMAIN, "redistList.item.file"); String nameFileUpCase = translation.getString(Translation.SEC_WMAIN, "redistList.item.fileUpperCase"); String nameFiles = translation.getString(Translation.SEC_WMAIN, "redistList.item.files"); String nameFolder = translation.getString(Translation.SEC_WMAIN, "redistList.item.folder"); String nameFolderUpCase = translation.getString(Translation.SEC_WMAIN, "redistList.item.folderUppercase"); String nameFolders = translation.getString(Translation.SEC_WMAIN, "redistList.item.folders"); model = new RedistTableModel(translation); setTableModelUI(); List<File> srcFolders = new ArrayList<>(32); if (fSteamDir.exists()) { srcFolders.add(fSteamDir); } File[] customFolders1 = customFoldersListStrToFiles(); for (File customFolder : customFolders1) { if (!srcFolders.contains(customFolder)) { srcFolders.add(customFolder); } } List<File> allFiles = new ArrayList<>(1024); FileUtils.listDir(thisframe, allFiles, srcFolders, config.getMaDepth(), dangerousFolders); List<Redist> checkedFiles = new ArrayList<>(128); List<Redist> checkedFolders = new ArrayList<>(128); FileComparator tc = new FileComparator( allFiles, patternsCfg.getRedistFilePatternsAndDesc(patternsCfg.getEnableExperimentalPatterns()), checkedFiles, true); try { //Log.info("debug: FileComparator on files"); tc.start(); } catch (InterruptedException ex) { Log.error(ex); } tc = new FileComparator( allFiles, patternsCfg.getRedistFolderPatternsAndDesc(patternsCfg.getEnableExperimentalPatterns()), checkedFolders, false); try { //Log.info("debug: FileComparator on folders"); tc.start(); } catch (InterruptedException ex) { Log.error(ex); } uncheckedRedistPathList = uncheckedItems.getUncheckedItems(); checkedFiles.stream().forEach((redist) -> { boolean checked = !uncheckedRedistPathList.contains(redist.getFile().getAbsolutePath()); model.addRow(new Object[]{ checked, redist.getFile().getAbsolutePath(), redist.getSize(), " (" + nameFileUpCase + ") " + redist.getDescription()}); }); checkedFolders.stream().forEach((redist) -> { boolean check = !uncheckedRedistPathList.contains(redist.getFile().getAbsolutePath() + File.separatorChar); model.addRow(new Object[]{ check, redist.getFile().getAbsolutePath() + File.separatorChar, redist.getSize(), " (" + nameFolderUpCase + ") " + redist.getDescription()}); }); int nbFiles = checkedFiles.size(); int nbFolders = checkedFolders.size(); jPanelList.setBorder(BorderFactory.createTitledBorder(tblRedistLabelDefault + " " + nbFiles + " " + (nbFiles > 1 ? nameFiles : nameFile) + ", " + checkedFolders.size() + " " + (nbFolders > 1 ? nameFolders : nameFolder))); recomputeTotalSizeMB(); }catch (InfinitiveLoopException | IOException ex) { Log.error(ex); } finally { jButtonStopSearch.setVisible(false); buttonReload.setText(btnReloadLabelInitial); enableAllUI(true); boolean rdistFound = model.getRowCount() > 0; jButtonRemoveRedistItemsFromDisk.setEnabled(rdistFound); buttonReload.setEnabled(true); } }); tJob.start(); } else { jButtonRemoveRedistItemsFromDisk.setEnabled(false); buttonReload.setEnabled(true); } } else { jButtonRemoveRedistItemsFromDisk.setEnabled(false); buttonReload.setEnabled(true); } } private void setTableModelUI() { jTableRedistList.setModel(model); RowSorter<TableModel> sorter = new TableRowSorter<>(model); jTableRedistList.setRowSorter(sorter); jTableRedistList.getColumnModel().getColumn(0).setPreferredWidth(50); jTableRedistList.getColumnModel().getColumn(0).setMinWidth(10); jTableRedistList.getColumnModel().getColumn(0).setMaxWidth(100); jTableRedistList.getColumnModel().getColumn(2).setPreferredWidth(80); jTableRedistList.getColumnModel().getColumn(2).setMinWidth(10); jTableRedistList.getColumnModel().getColumn(2).setMaxWidth(200); jTableRedistList.getColumnModel().getColumn(3).setPreferredWidth(275); jTableRedistList.getColumnModel().getColumn(3).setMinWidth(50); jTableRedistList.getColumnModel().getColumn(3).setMaxWidth(500); } private void enableAllUI(boolean enable) { jButtonLocateSteamDir.setEnabled(enable); jButtonManualSteamDirSearch.setEnabled(enable); jButtonRemoveRedistItemsFromDisk.setEnabled(enable); jTableRedistList.setEnabled(enable); jTextFieldSteamDir.setEnabled(enable); jButtonAddCustomFolder.setEnabled(enable); jButtonRemoveCustomFolder.setEnabled(enable); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jPanelMain = new JPanel(); jLabelSteamDir = new JLabel(); jTextFieldSteamDir = new JTextField(); jButtonLocateSteamDir = new JButton(); jButtonManualSteamDirSearch = new JButton(); jPanelList = new JPanel(); jButtonReloadRedistList = new JButton(); jButtonRemoveRedistItemsFromDisk = new JButton(); jScrollPane1 = new JScrollPane(); jTableRedistList = new JTable(); jButtonStopSearch = new JButton(); jLabelCustomFolders = new JLabel(); jScrollPane2 = new JScrollPane(); jListCustomFolders = new JList<>(); jButtonAddCustomFolder = new JButton(); jButtonRemoveCustomFolder = new JButton(); jToolBarMain = new JToolBar(); jSeparatorA = new JToolBar.Separator(); jButtonToolbarOptions = new JButton(); jSeparatorB = new JToolBar.Separator(); jButtonToolbarCheckforupdates = new JButton(); jButtonToolbarAbout = new JButton(); jPanelAppVersion = new JPanel(); jLabelAppVersion = new JLabel(); jButtonGithub = new JButton(); jButtonTwitter = new JButton(); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setBackground(new Color(255, 255, 255)); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { formWindowClosing(evt); } }); addWindowStateListener(new WindowStateListener() { public void windowStateChanged(WindowEvent evt) { formWindowStateChanged(evt); } }); jPanelMain.setBackground(new Color(255, 255, 255)); jLabelSteamDir.setFont(new Font("Dialog", 0, 13)); // NOI18N jLabelSteamDir.setText("Steam folder :"); jTextFieldSteamDir.setFont(new Font("DialogInput", 0, 13)); // NOI18N jTextFieldSteamDir.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent evt) { jTextFieldSteamDirKeyReleased(evt); } }); jButtonLocateSteamDir.setText("Try to locate Steam automatically"); jButtonLocateSteamDir.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonLocateSteamDirActionPerformed(evt); } }); jButtonManualSteamDirSearch.setFont(new Font("Dialog", 1, 11)); // NOI18N jButtonManualSteamDirSearch.setText("..."); jButtonManualSteamDirSearch.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonManualSteamDirSearchActionPerformed(evt); } }); jPanelList.setBackground(new Color(255, 255, 255)); jPanelList.setBorder(BorderFactory.createTitledBorder("Redistributable packages found :")); jPanelList.setFont(new Font("Dialog", 0, 13)); // NOI18N jButtonReloadRedistList.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_search.png"))); // NOI18N jButtonReloadRedistList.setText("Search"); jButtonReloadRedistList.setEnabled(false); jButtonReloadRedistList.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonReloadRedistListActionPerformed(evt); } }); jButtonRemoveRedistItemsFromDisk.setForeground(new Color(0, 0, 153)); jButtonRemoveRedistItemsFromDisk.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_clean.png"))); // NOI18N jButtonRemoveRedistItemsFromDisk.setText("Remove selected items from disk"); jButtonRemoveRedistItemsFromDisk.setEnabled(false); jButtonRemoveRedistItemsFromDisk.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonRemoveRedistItemsFromDiskActionPerformed(evt); } }); jTableRedistList.setFont(new Font("Tahoma", 0, 12)); // NOI18N jTableRedistList.setForeground(new Color(51, 51, 51)); jTableRedistList.setModel(new DefaultTableModel( new Object [][] { {}, {}, {}, {} }, new String [] { } )); jTableRedistList.setRowMargin(2); jTableRedistList.setSelectionBackground(new Color(255, 255, 153)); jTableRedistList.setSelectionForeground(new Color(0, 0, 0)); jTableRedistList.setShowHorizontalLines(false); jTableRedistList.setShowVerticalLines(false); jTableRedistList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { jTableRedistListMouseClicked(evt); } }); jTableRedistList.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent evt) { jTableRedistListKeyPressed(evt); } }); jScrollPane1.setViewportView(jTableRedistList); jButtonStopSearch.setFont(new Font("Dialog", 0, 13)); // NOI18N jButtonStopSearch.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_stop_search.png"))); // NOI18N jButtonStopSearch.setFocusable(false); jButtonStopSearch.setRequestFocusEnabled(false); jButtonStopSearch.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonStopSearchActionPerformed(evt); } }); GroupLayout jPanelListLayout = new GroupLayout(jPanelList); jPanelList.setLayout(jPanelListLayout); jPanelListLayout.setHorizontalGroup(jPanelListLayout.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, jPanelListLayout.createSequentialGroup() .addContainerGap() .addGroup(jPanelListLayout.createParallelGroup(Alignment.TRAILING) .addComponent(jScrollPane1) .addGroup(jPanelListLayout.createSequentialGroup() .addComponent(jButtonReloadRedistList) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(jButtonStopSearch, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButtonRemoveRedistItemsFromDisk))) .addContainerGap()) ); jPanelListLayout.setVerticalGroup(jPanelListLayout.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, jPanelListLayout.createSequentialGroup() .addContainerGap() .addGroup(jPanelListLayout.createParallelGroup(Alignment.CENTER) .addComponent(jButtonReloadRedistList) .addComponent(jButtonRemoveRedistItemsFromDisk) .addComponent(jButtonStopSearch)) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 118, Short.MAX_VALUE) .addContainerGap()) ); jLabelCustomFolders.setFont(new Font("Dialog", 0, 13)); // NOI18N jLabelCustomFolders.setText("<html>Custom folders list :</html>"); jLabelCustomFolders.setVerticalAlignment(SwingConstants.TOP); jListCustomFolders.setFont(new Font("DialogInput", 0, 13)); // NOI18N jListCustomFolders.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); jListCustomFolders.setRequestFocusEnabled(false); jScrollPane2.setViewportView(jListCustomFolders); jButtonAddCustomFolder.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_add_folder.png"))); // NOI18N jButtonAddCustomFolder.setText("Add to list..."); jButtonAddCustomFolder.setMaximumSize(new Dimension(119, 23)); jButtonAddCustomFolder.setMinimumSize(new Dimension(119, 23)); jButtonAddCustomFolder.setRequestFocusEnabled(false); jButtonAddCustomFolder.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonAddCustomFolderActionPerformed(evt); } }); jButtonRemoveCustomFolder.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_del_folder.png"))); // NOI18N jButtonRemoveCustomFolder.setText("Remove from list"); jButtonRemoveCustomFolder.setMaximumSize(new Dimension(149, 23)); jButtonRemoveCustomFolder.setMinimumSize(new Dimension(149, 23)); jButtonRemoveCustomFolder.setRequestFocusEnabled(false); jButtonRemoveCustomFolder.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonRemoveCustomFolderActionPerformed(evt); } }); GroupLayout jPanelMainLayout = new GroupLayout(jPanelMain); jPanelMain.setLayout(jPanelMainLayout); jPanelMainLayout.setHorizontalGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING) .addComponent(jPanelList, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanelMainLayout.createSequentialGroup() .addContainerGap() .addGroup(jPanelMainLayout.createParallelGroup(Alignment.TRAILING) .addGroup(jPanelMainLayout.createSequentialGroup() .addComponent(jLabelCustomFolders, GroupLayout.PREFERRED_SIZE, 104, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(jScrollPane2, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE)) .addGroup(jPanelMainLayout.createSequentialGroup() .addComponent(jLabelSteamDir) .addPreferredGap(ComponentPlacement.UNRELATED) .addComponent(jTextFieldSteamDir))) .addPreferredGap(ComponentPlacement.RELATED) .addGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING) .addGroup(jPanelMainLayout.createSequentialGroup() .addComponent(jButtonManualSteamDirSearch, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(jButtonLocateSteamDir, GroupLayout.PREFERRED_SIZE, 225, GroupLayout.PREFERRED_SIZE)) .addComponent(jButtonAddCustomFolder, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(jButtonRemoveCustomFolder, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addContainerGap()) ); jPanelMainLayout.setVerticalGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING) .addGroup(jPanelMainLayout.createSequentialGroup() .addContainerGap() .addGroup(jPanelMainLayout.createParallelGroup(Alignment.BASELINE) .addComponent(jLabelSteamDir) .addComponent(jTextFieldSteamDir, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(jButtonLocateSteamDir) .addComponent(jButtonManualSteamDirSearch)) .addPreferredGap(ComponentPlacement.UNRELATED) .addGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING, false) .addComponent(jScrollPane2, GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) .addGroup(jPanelMainLayout.createSequentialGroup() .addComponent(jButtonAddCustomFolder, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(jButtonRemoveCustomFolder, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addComponent(jLabelCustomFolders, GroupLayout.DEFAULT_SIZE, 81, Short.MAX_VALUE)) .addGap(18, 18, 18) .addComponent(jPanelList, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); jToolBarMain.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); jToolBarMain.setFloatable(false); jToolBarMain.setRollover(true); jToolBarMain.setAlignmentY(0.5F); jToolBarMain.add(jSeparatorA); jButtonToolbarOptions.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_options.png"))); // NOI18N jButtonToolbarOptions.setToolTipText("Options"); jButtonToolbarOptions.setFocusable(false); jButtonToolbarOptions.setHorizontalTextPosition(SwingConstants.CENTER); jButtonToolbarOptions.setVerticalTextPosition(SwingConstants.BOTTOM); jButtonToolbarOptions.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonToolbarOptionsActionPerformed(evt); } }); jToolBarMain.add(jButtonToolbarOptions); jToolBarMain.add(jSeparatorB); jButtonToolbarCheckforupdates.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_update.png"))); // NOI18N jButtonToolbarCheckforupdates.setToolTipText("Check for updates"); jButtonToolbarCheckforupdates.setFocusable(false); jButtonToolbarCheckforupdates.setHorizontalTextPosition(SwingConstants.CENTER); jButtonToolbarCheckforupdates.setVerticalTextPosition(SwingConstants.BOTTOM); jButtonToolbarCheckforupdates.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonToolbarCheckforupdatesActionPerformed(evt); } }); jToolBarMain.add(jButtonToolbarCheckforupdates); jButtonToolbarAbout.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/famfamfam_btn_about.png"))); // NOI18N jButtonToolbarAbout.setToolTipText("About TikiOne steam Cleaner"); jButtonToolbarAbout.setFocusable(false); jButtonToolbarAbout.setHorizontalTextPosition(SwingConstants.CENTER); jButtonToolbarAbout.setVerticalTextPosition(SwingConstants.BOTTOM); jButtonToolbarAbout.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonToolbarAboutActionPerformed(evt); } }); jToolBarMain.add(jButtonToolbarAbout); jPanelAppVersion.setBackground(new Color(255, 102, 153)); jPanelAppVersion.setForeground(new Color(255, 255, 255)); jLabelAppVersion.setFont(new Font("Dialog", 1, 14)); // NOI18N jLabelAppVersion.setForeground(new Color(255, 255, 255)); jLabelAppVersion.setHorizontalAlignment(SwingConstants.CENTER); jLabelAppVersion.setText("version here"); GroupLayout jPanelAppVersionLayout = new GroupLayout(jPanelAppVersion); jPanelAppVersion.setLayout(jPanelAppVersionLayout); jPanelAppVersionLayout.setHorizontalGroup(jPanelAppVersionLayout.createParallelGroup(Alignment.LEADING) .addComponent(jLabelAppVersion, GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE) ); jPanelAppVersionLayout.setVerticalGroup(jPanelAppVersionLayout.createParallelGroup(Alignment.LEADING) .addComponent(jLabelAppVersion, GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE) ); jButtonGithub.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/social_github.png"))); // NOI18N jButtonGithub.setToolTipText(""); jButtonGithub.setContentAreaFilled(false); jButtonGithub.setCursor(new Cursor(Cursor.HAND_CURSOR)); jButtonGithub.setFocusPainted(false); jButtonGithub.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonGithubActionPerformed(evt); } }); jButtonTwitter.setIcon(new ImageIcon(getClass().getResource("/fr/tikione/steam/cleaner/gui/icons/social_twitter.png"))); // NOI18N jButtonTwitter.setToolTipText(""); jButtonTwitter.setContentAreaFilled(false); jButtonTwitter.setCursor(new Cursor(Cursor.HAND_CURSOR)); jButtonTwitter.setFocusPainted(false); jButtonTwitter.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { jButtonTwitterActionPerformed(evt); } }); GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING) .addComponent(jPanelMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(jToolBarMain, GroupLayout.PREFERRED_SIZE, 274, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButtonGithub, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(jButtonTwitter, GroupLayout.PREFERRED_SIZE, 29, GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(jPanelAppVersion, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) ); layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.LEADING) .addComponent(jToolBarMain, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(jPanelAppVersion, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(jButtonGithub) .addComponent(jButtonTwitter)) .addGap(10, 10, 10) .addComponent(jPanelMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); pack(); }// </editor-fold>//GEN-END:initComponents private void jTextFieldSteamDirKeyReleased(KeyEvent evt) {//GEN-FIRST:event_jTextFieldSteamDirKeyReleased }//GEN-LAST:event_jTextFieldSteamDirKeyReleased private void locateSteamDir() { try { fSteamDir = null; List<String> steamPossibleFoldersTbl = config.getPossibleSteamFolders(); SEARCH_STEAM_DIR: for (String s : steamPossibleFoldersTbl) { try { File fPossibleSteamDir = new File(s); if (fPossibleSteamDir.exists() && fPossibleSteamDir.isDirectory()) { jTextFieldSteamDir.setText(fPossibleSteamDir.getAbsolutePath()); fSteamDir = fPossibleSteamDir; break; } } catch (Exception ex) { Log.error(ex); } } if (fSteamDir == null) { jTextFieldSteamDir.setText(""); if (listModel == null || listModel.isEmpty()) { } } } catch (CharConversionException | InfinitiveLoopException ex) { Log.error(ex); } } private void jButtonLocateSteamDirActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonLocateSteamDirActionPerformed locateSteamDir(); }//GEN-LAST:event_jButtonLocateSteamDirActionPerformed private void jButtonManualSteamDirSearchActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonManualSteamDirSearchActionPerformed JFileChooser dialogue = new JFileChooser(); dialogue.setMultiSelectionEnabled(false); dialogue.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); dialogue.setAcceptAllFileFilterUsed(false); if (dialogue.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File folder = dialogue.getSelectedFile(); if (folder != null) { jTextFieldSteamDir.setText(folder.getAbsolutePath()); fSteamDir = new File(jTextFieldSteamDir.getText()); } else { jTextFieldSteamDir.setText(""); } } }//GEN-LAST:event_jButtonManualSteamDirSearchActionPerformed private void jButtonReloadRedistListActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonReloadRedistListActionPerformed searchRedistPackagesOnDisk(jButtonReloadRedistList); CLOSING_APP = false; }//GEN-LAST:event_jButtonReloadRedistListActionPerformed private void jButtonRemoveRedistItemsFromDiskActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonRemoveRedistItemsFromDiskActionPerformed memorizeUncheckedItemsToConf(); jButtonRemoveRedistItemsFromDisk.setText(translation.getString(Translation.SEC_WMAIN, "button.removeSelectedItems")); List<File> filesDoDel = new ArrayList<>(8); List<File> foldersToDel = new ArrayList<>(8); for (int row = 0; row < model.getRowCount(); row++) { boolean selected = (Boolean) model.getValueAt(row, 0); if (selected) { String path = (String) model.getValueAt(row, 1); if (path.endsWith(File.separator)) { foldersToDel.add(new File(path)); } else { filesDoDel.add(new File(path)); } } } try { JDialogDeletionDirect delFrame = new JDialogDeletionDirect(this, true, translation); delFrame.setFilesToDelete(filesDoDel, foldersToDel); delFrame.setVisible(true); jButtonRemoveRedistItemsFromDisk.setEnabled(false); model = new RedistTableModel(translation); setTableModelUI(); jPanelList.setBorder(BorderFactory.createTitledBorder(tblRedistLabelDefault)); } catch (IOException ex) { Log.error(ex); } }//GEN-LAST:event_jButtonRemoveRedistItemsFromDiskActionPerformed private void checkForUpdates() { new Thread(() -> { String latestVersion = UpdateManager.getLatestVersion(); if (!UpdateManager.IsUpToDate(latestVersion)) { setTitle(getTitle() + " " + translation.getString(Translation.SEC_WMAIN, "title.newVersionMsg") .replace("{0}", UpdateManager.normalizeVersionStr(latestVersion))); } }).start(); } public static boolean isCLOSING_APP() { return CLOSING_APP; } public static void setCLOSING_APP(boolean closingApp) { JFrameMain.CLOSING_APP = closingApp; } private void formWindowClosing(WindowEvent evt) {//GEN-FIRST:event_formWindowClosing setCLOSING_APP(true); memorizeUncheckedItemsToConf(); Dimension windowDimension = this.getSize(); int height = windowDimension.height; int width = windowDimension.width; config.setUILatestHeight(height); config.setUILatestWidth(width); if (!jTextFieldSteamDir.getText().isEmpty() && null != fSteamDir) { String steamDirToSave = fSteamDir.getAbsolutePath().replaceAll("\\\\", "/"); if (!steamDirToSave.endsWith("/")) { steamDirToSave += "/"; } config.setLatestSteamFolder(steamDirToSave); } else { config.setLatestSteamFolder(""); } try { config.save(); patternsCfg.save(); uncheckedItems.save(); customFolders.save(); } catch (IOException ex) { Log.error(ex); } }//GEN-LAST:event_formWindowClosing private void formWindowStateChanged(WindowEvent evt) {//GEN-FIRST:event_formWindowStateChanged config.setUIState(evt.getNewState()); }//GEN-LAST:event_formWindowStateChanged private void jButtonToolbarOptionsActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonToolbarOptionsActionPerformed try { JDialogOptionsTabs optionsFrame = new JDialogOptionsTabs(this, true, translation); optionsFrame.setVisible(true); } catch (Exception ex) { Log.error(ex); } }//GEN-LAST:event_jButtonToolbarOptionsActionPerformed private void jButtonToolbarCheckforupdatesActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonToolbarCheckforupdatesActionPerformed JDialogCheckForUpdates checkForUpdatesFrame = new JDialogCheckForUpdates(this, true, translation); checkForUpdatesFrame.setVisible(true); }//GEN-LAST:event_jButtonToolbarCheckforupdatesActionPerformed private void jButtonToolbarAboutActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonToolbarAboutActionPerformed JDialogAbout aboutFrame = new JDialogAbout(this, true, translation); aboutFrame.setVisible(true); }//GEN-LAST:event_jButtonToolbarAboutActionPerformed private void jButtonAddCustomFolderActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonAddCustomFolderActionPerformed JFileChooser dialogue = new JFileChooser(); dialogue.setMultiSelectionEnabled(false); dialogue.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); dialogue.setAcceptAllFileFilterUsed(false); if (dialogue.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File folder = dialogue.getSelectedFile(); listModel.addElement(folder); memorizeCustomFoldersToConf(); } }//GEN-LAST:event_jButtonAddCustomFolderActionPerformed private void jButtonRemoveCustomFolderActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonRemoveCustomFolderActionPerformed int selIdx = jListCustomFolders.getSelectedIndex(); if (selIdx > -1) { listModel.remove(selIdx); memorizeCustomFoldersToConf(); if (listModel.isEmpty() && fSteamDir != null && !fSteamDir.exists()) { } } }//GEN-LAST:event_jButtonRemoveCustomFolderActionPerformed private void jButtonStopSearchActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonStopSearchActionPerformed CLOSING_APP = true; }//GEN-LAST:event_jButtonStopSearchActionPerformed private void jButtonGithubActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonGithubActionPerformed UpdateManager.extBrowser("https://github.com/jonathanlermitage/tikione-steam-cleaner"); }//GEN-LAST:event_jButtonGithubActionPerformed private void jButtonTwitterActionPerformed(ActionEvent evt) {//GEN-FIRST:event_jButtonTwitterActionPerformed UpdateManager.extBrowser("https://twitter.com/JLermitage"); }//GEN-LAST:event_jButtonTwitterActionPerformed private void jTableRedistListMouseClicked(MouseEvent evt) {//GEN-FIRST:event_jTableRedistListMouseClicked memorizeCustomFoldersToConf(); recomputeTotalSizeMB(); }//GEN-LAST:event_jTableRedistListMouseClicked private void jTableRedistListKeyPressed(KeyEvent evt) {//GEN-FIRST:event_jTableRedistListKeyPressed memorizeCustomFoldersToConf(); recomputeTotalSizeMB(); }//GEN-LAST:event_jTableRedistListKeyPressed // Variables declaration - do not modify//GEN-BEGIN:variables private JButton jButtonAddCustomFolder; private JButton jButtonGithub; private JButton jButtonLocateSteamDir; private JButton jButtonManualSteamDirSearch; private JButton jButtonReloadRedistList; private JButton jButtonRemoveCustomFolder; private JButton jButtonRemoveRedistItemsFromDisk; private JButton jButtonStopSearch; private JButton jButtonToolbarAbout; private JButton jButtonToolbarCheckforupdates; private JButton jButtonToolbarOptions; private JButton jButtonTwitter; private JLabel jLabelAppVersion; private JLabel jLabelCustomFolders; private JLabel jLabelSteamDir; private JList<File> jListCustomFolders; private JPanel jPanelAppVersion; private JPanel jPanelList; private JPanel jPanelMain; private JScrollPane jScrollPane1; private JScrollPane jScrollPane2; private JToolBar.Separator jSeparatorA; private JToolBar.Separator jSeparatorB; private JTable jTableRedistList; private JTextField jTextFieldSteamDir; private JToolBar jToolBarMain; // End of variables declaration//GEN-END:variables }