From 1c644178cefa723855923b4ad7b2669bdf18e0a7 Mon Sep 17 00:00:00 2001 From: ATnayan Date: Sun, 5 Apr 2020 11:01:26 +0300 Subject: [PATCH 1/5] Add ability to open multiple jars in same window --- pom.xml | 2 +- src/us/deathmarine/luyten/FindAllBox.java | 11 ++- src/us/deathmarine/luyten/FindBox.java | 6 +- src/us/deathmarine/luyten/Luyten.java | 2 +- src/us/deathmarine/luyten/MainMenuBar.java | 6 +- src/us/deathmarine/luyten/MainWindow.java | 110 +++++++++++++++------ src/us/deathmarine/luyten/Model.java | 45 +++++---- 7 files changed, 120 insertions(+), 62 deletions(-) diff --git a/pom.xml b/pom.xml index d1787bf..42f9bfe 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 us.deathmarine luyten - 0.5.4 + 0.6.0 com.fifesoft diff --git a/src/us/deathmarine/luyten/FindAllBox.java b/src/us/deathmarine/luyten/FindAllBox.java index 92bb1e3..bf35849 100644 --- a/src/us/deathmarine/luyten/FindAllBox.java +++ b/src/us/deathmarine/luyten/FindAllBox.java @@ -65,11 +65,14 @@ public class FindAllBox extends JDialog { private Thread tmp_thread; + private MainWindow mainWindow; + public FindAllBox(final MainWindow mainWindow) { this.setDefaultCloseOperation(HIDE_ON_CLOSE); this.setHideOnEscapeButton(); progressBar = new JProgressBar(0, 100); + this.mainWindow = mainWindow; JLabel label = new JLabel("Find What:"); textField = new JTextField(); @@ -99,7 +102,7 @@ public class FindAllBox extends JDialog { String internalName = StringUtilities.removeRight(entryName, ".class"); TypeReference type = Model.metadataSystem.lookupType(internalName); try { - mainWindow.getModel().extractClassToTextPane(type, array[array.length - 1], entryName, + mainWindow.getSelectedModel().extractClassToTextPane(type, array[array.length - 1], entryName, null); } catch (Exception e) { Luyten.showExceptionDialog("Exception!", e); @@ -107,8 +110,8 @@ public class FindAllBox extends JDialog { } else { try { - JarFile jfile = new JarFile(MainWindow.model.getOpenedFile()); - mainWindow.getModel().extractSimpleFileEntryToTextPane( + JarFile jfile = new JarFile(mainWindow.getSelectedModel().getOpenedFile()); + mainWindow.getSelectedModel().extractSimpleFileEntryToTextPane( jfile.getInputStream(jfile.getEntry(entryName)), array[array.length - 1], entryName); jfile.close(); @@ -196,7 +199,7 @@ public class FindAllBox extends JDialog { classesList.clear(); ConfigSaver configSaver = ConfigSaver.getLoadedInstance(); DecompilerSettings settings = configSaver.getDecompilerSettings(); - File inFile = MainWindow.model.getOpenedFile(); + File inFile = mainWindow.getSelectedModel().getOpenedFile(); boolean filter = ConfigSaver.getLoadedInstance().getLuytenPreferences() .isFilterOutInnerClassEntries(); try { diff --git a/src/us/deathmarine/luyten/FindBox.java b/src/us/deathmarine/luyten/FindBox.java index d43dc8f..0c14256 100644 --- a/src/us/deathmarine/luyten/FindBox.java +++ b/src/us/deathmarine/luyten/FindBox.java @@ -54,7 +54,7 @@ public class FindBox extends JDialog { JLabel label = new JLabel("Find What:"); textField = new JTextField(); - RSyntaxTextArea pane = mainWindow.getModel().getCurrentTextArea(); + RSyntaxTextArea pane = mainWindow.getSelectedModel().getCurrentTextArea(); if (pane != null) { textField.setText(pane.getSelectedText()); } @@ -132,7 +132,7 @@ public class FindBox extends JDialog { if (textField.getText().length() == 0) return; - RSyntaxTextArea pane = mainWindow.getModel().getCurrentTextArea(); + RSyntaxTextArea pane = mainWindow.getSelectedModel().getCurrentTextArea(); if (pane == null) return; @@ -207,7 +207,7 @@ public class FindBox extends JDialog { public void actionPerformed(ActionEvent e) { if (textField.getText().length() == 0) return; - RSyntaxTextArea pane = mainWindow.getModel().getCurrentTextArea(); + RSyntaxTextArea pane = mainWindow.getSelectedModel().getCurrentTextArea(); if (pane == null) return; SearchContext context = new SearchContext(); diff --git a/src/us/deathmarine/luyten/Luyten.java b/src/us/deathmarine/luyten/Luyten.java index d8139d7..e0495d2 100644 --- a/src/us/deathmarine/luyten/Luyten.java +++ b/src/us/deathmarine/luyten/Luyten.java @@ -75,7 +75,7 @@ public class Luyten { if (mainWindow != null) { synchronized (pendingFiles) { for (File f : pendingFiles) { - mainWindow.getModel().loadFile(f); + mainWindow.loadNewFile(f); } pendingFiles.clear(); } diff --git a/src/us/deathmarine/luyten/MainMenuBar.java b/src/us/deathmarine/luyten/MainMenuBar.java index b9af8ba..bd108c7 100644 --- a/src/us/deathmarine/luyten/MainMenuBar.java +++ b/src/us/deathmarine/luyten/MainMenuBar.java @@ -167,7 +167,7 @@ public class MainMenuBar extends JMenuBar { menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - mainWindow.getModel().loadFile(file); + mainWindow.loadNewFile(file); } }); recentFiles.add(menuItem); @@ -196,12 +196,12 @@ public class MainMenuBar extends JMenuBar { menuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - JTabbedPane house = mainWindow.getModel().house; + JTabbedPane house = mainWindow.getSelectedModel().house; if (e.getModifiers() != 2 || house.getTabCount() == 0) mainWindow.onCloseFileMenu(); else { - mainWindow.getModel().closeOpenTab(house.getSelectedIndex()); + mainWindow.getSelectedModel().closeOpenTab(house.getSelectedIndex()); } } }); diff --git a/src/us/deathmarine/luyten/MainWindow.java b/src/us/deathmarine/luyten/MainWindow.java index 68d27dc..26db7ce 100644 --- a/src/us/deathmarine/luyten/MainWindow.java +++ b/src/us/deathmarine/luyten/MainWindow.java @@ -15,20 +15,15 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Vector; +import java.util.concurrent.Callable; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JSplitPane; -import javax.swing.KeyStroke; +import javax.swing.*; import javax.swing.border.BevelBorder; +import javax.swing.plaf.basic.BasicTabbedPaneUI; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; @@ -39,6 +34,7 @@ public class MainWindow extends JFrame { private static final long serialVersionUID = 5265556630724988013L; private static final String TITLE = "Luyten"; + private static final String DEFAULT_TAB = "#DEFAULT"; public static Model model; private JProgressBar bar; @@ -50,13 +46,16 @@ public class MainWindow extends JFrame { private LuytenPreferences luytenPrefs; private FileDialog fileDialog; private FileSaver fileSaver; + private JTabbedPane jarsTabbedPane; + private List jarModels; public MainMenuBar mainMenuBar; public MainWindow(File fileFromCommandLine) { configSaver = ConfigSaver.getLoadedInstance(); windowPosition = configSaver.getMainWindowPosition(); luytenPrefs = configSaver.getLuytenPreferences(); - + + jarModels = new ArrayList<>(); mainMenuBar = new MainMenuBar(this); this.setJMenuBar(mainMenuBar); @@ -85,7 +84,18 @@ public class MainWindow extends JFrame { panel2.add(bar); model = new Model(this); - this.getContentPane().add(model); + jarsTabbedPane = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); + jarsTabbedPane.setUI(new BasicTabbedPaneUI() { + @Override + protected int calculateTabAreaHeight(int tab_placement, int run_count, int max_tab_height) { + if (jarsTabbedPane.indexOfTab(DEFAULT_TAB) == -1) + return super.calculateTabAreaHeight(tab_placement, run_count, max_tab_height); + else + return 0; + } + }); + jarsTabbedPane.addTab("#DEFAULT", model); + this.getContentPane().add(jarsTabbedPane); JSplitPane spt = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panel1, panel2) { private static final long serialVersionUID = 2189946972124687305L; @@ -133,24 +143,58 @@ public class MainWindow extends JFrame { if(RecentFiles.load() > 0) mainMenuBar.updateRecentFiles(); } + private void createDefaultTab() { + jarsTabbedPane.addTab(DEFAULT_TAB, new Model(this)); + } + + private void removeDefaultTab() { + jarsTabbedPane.remove(jarsTabbedPane.indexOfTab(DEFAULT_TAB)); + } + public void onOpenFileMenu() { File selectedFile = fileDialog.doOpenDialog(); if (selectedFile != null) { System.out.println("[Open]: Opening " + selectedFile.getAbsolutePath()); - - this.getModel().loadFile(selectedFile); + this.loadNewFile(selectedFile); + } + } + + public void loadNewFile(final File file) { + Model jarModel = new Model(this); + jarModel.loadFile(file); + jarModels.add(jarModel); + jarsTabbedPane.addTab(file.getName(), jarModel); + jarsTabbedPane.setSelectedComponent(jarModel); + + final String tabName = file.getName(); + int index = jarsTabbedPane.indexOfTab(tabName); + Model.Tab tabUI = new Model.Tab(tabName, new Callable() { + @Override + public Void call() throws Exception { + int index = jarsTabbedPane.indexOfTab(tabName); + jarsTabbedPane.remove(index); + if (jarsTabbedPane.getTabCount() == 0) { + createDefaultTab(); + } + return null; + } + }); + jarsTabbedPane.setTabComponentAt(index, tabUI); + if (jarsTabbedPane.indexOfTab(DEFAULT_TAB) != -1 && jarsTabbedPane.getTabCount() > 1) { + removeDefaultTab(); } } public void onCloseFileMenu() { - this.getModel().closeFile(); + this.getSelectedModel().closeFile(); + jarModels.remove(getSelectedModel()); } public void onSaveAsMenu() { - RSyntaxTextArea pane = this.getModel().getCurrentTextArea(); + RSyntaxTextArea pane = this.getSelectedModel().getCurrentTextArea(); if (pane == null) return; - String tabTitle = this.getModel().getCurrentTabTitle(); + String tabTitle = this.getSelectedModel().getCurrentTabTitle(); if (tabTitle == null) return; @@ -162,7 +206,7 @@ public class MainWindow extends JFrame { } public void onSaveAllMenu() { - File openedFile = this.getModel().getOpenedFile(); + File openedFile = this.getSelectedModel().getOpenedFile(); if (openedFile == null) return; @@ -187,7 +231,7 @@ public class MainWindow extends JFrame { public void onSelectAllMenu() { try { - RSyntaxTextArea pane = this.getModel().getCurrentTextArea(); + RSyntaxTextArea pane = this.getSelectedModel().getCurrentTextArea(); if (pane != null) { pane.requestFocusInWindow(); pane.setSelectionStart(0); @@ -200,7 +244,7 @@ public class MainWindow extends JFrame { public void onFindMenu() { try { - RSyntaxTextArea pane = this.getModel().getCurrentTextArea(); + RSyntaxTextArea pane = this.getSelectedModel().getCurrentTextArea(); if (pane != null) { if (findBox == null) findBox = new FindBox(this); @@ -229,7 +273,7 @@ public class MainWindow extends JFrame { bar.setVisible(true); bar.setIndeterminate(true); String legalStr = getLegalStr(); - MainWindow.this.getModel().showLegal(legalStr); + getSelectedModel().showLegal(legalStr); } finally { bar.setIndeterminate(false); bar.setVisible(false); @@ -251,7 +295,7 @@ public class MainWindow extends JFrame { } myCL = myCL.getParent(); } - MainWindow.this.getModel().show("Debug", sb.toString()); + this.getSelectedModel().show("Debug", sb.toString()); } finally { bar.setIndeterminate(false); bar.setVisible(false); @@ -295,21 +339,27 @@ public class MainWindow extends JFrame { } public void onThemesChanged() { - this.getModel().changeTheme(luytenPrefs.getThemeXml()); - luytenPrefs.setFont_size(this.getModel().getTheme().baseFont.getSize()); + for (Model jarModel : jarModels) { + jarModel.changeTheme(luytenPrefs.getThemeXml()); + luytenPrefs.setFont_size(jarModel.getTheme().baseFont.getSize()); + } } public void onSettingsChanged() { - this.getModel().updateOpenClasses(); + for (Model jarModel : jarModels) { + jarModel.updateOpenClasses(); + } } public void onTreeSettingsChanged() { - this.getModel().updateTree(); + for (Model jarModel : jarModels) { + jarModel.updateTree(); + } } public void onFileDropped(File file) { if (file != null) { - this.getModel().loadFile(file); + this.loadNewFile(file); } } @@ -326,7 +376,7 @@ public class MainWindow extends JFrame { } public void onNavigationRequest(String uniqueStr) { - this.getModel().navigateTo(uniqueStr); + this.getSelectedModel().navigateTo(uniqueStr); } private void adjustWindowPositionBySavedState() { @@ -426,8 +476,8 @@ public class MainWindow extends JFrame { mainComponent.getActionMap().put("ESCAPE", escapeAction); } - public Model getModel() { - return model; + public Model getSelectedModel() { + return (Model) jarsTabbedPane.getSelectedComponent(); } public JProgressBar getBar() { diff --git a/src/us/deathmarine/luyten/Model.java b/src/us/deathmarine/luyten/Model.java index 2d0b802..2ecfb8e 100644 --- a/src/us/deathmarine/luyten/Model.java +++ b/src/us/deathmarine/luyten/Model.java @@ -5,12 +5,7 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.awt.event.*; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -28,6 +23,7 @@ import java.util.List; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.concurrent.Callable; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -213,8 +209,14 @@ public class Model extends JSplitPane { house.addTab(title, rTextScrollPane); index = house.indexOfComponent(rTextScrollPane); house.setSelectedIndex(index); - Tab ct = new Tab(title); - ct.getButton().addMouseListener(new CloseTab(title)); + Tab ct = new Tab(title, new Callable() { + @Override + public Void call() throws Exception { + int index = house.indexOfTab(title); + closeOpenTab(index); + return null; + } + }); house.setTabComponentAt(index, ct); } else { house.setSelectedIndex(index); @@ -586,25 +588,28 @@ public class Model extends JSplitPane { } } - private class Tab extends JPanel { - private static final long serialVersionUID = -514663009333644974L; + public static class Tab extends JPanel { + private JLabel tabTitle; private JLabel closeButton = new JLabel(new ImageIcon( Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/resources/icon_close.png")))); - private JLabel tabTitle = new JLabel(); - private String title = ""; - public Tab(String t) { + public Tab(String title, final Callable onCloseTabAction) { super(new GridBagLayout()); this.setOpaque(false); - - this.title = t; this.tabTitle = new JLabel(title); - this.createTab(); - } - - public JLabel getButton() { - return this.closeButton; + closeButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + try { + if (onCloseTabAction != null) { + onCloseTabAction.call(); + } + } catch (Exception ex) { + Luyten.showExceptionDialog("Exception!", ex); + } + } + }); } public void createTab() { From 0b3339a7e98e42ea176af2571d2273904752f19d Mon Sep 17 00:00:00 2001 From: ATnayan Date: Sun, 5 Apr 2020 13:39:50 +0300 Subject: [PATCH 2/5] Make tab appear for single jar when opened from OS --- src/us/deathmarine/luyten/LuytenOsx.java | 2 +- src/us/deathmarine/luyten/MainWindow.java | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/us/deathmarine/luyten/LuytenOsx.java b/src/us/deathmarine/luyten/LuytenOsx.java index 46670ae..1350c20 100644 --- a/src/us/deathmarine/luyten/LuytenOsx.java +++ b/src/us/deathmarine/luyten/LuytenOsx.java @@ -16,7 +16,7 @@ public class LuytenOsx extends Luyten { Application app = new Application(); app.addApplicationListener(new ApplicationAdapter() { public void handleOpenFile(ApplicationEvent e) { - Luyten.openFileInInstance(new File(e.getFilename())); + Luyten.addToPendingFiles(new File(e.getFilename())); } public void handleQuit(ApplicationEvent e) { diff --git a/src/us/deathmarine/luyten/MainWindow.java b/src/us/deathmarine/luyten/MainWindow.java index 26db7ce..4153a7e 100644 --- a/src/us/deathmarine/luyten/MainWindow.java +++ b/src/us/deathmarine/luyten/MainWindow.java @@ -36,7 +36,6 @@ public class MainWindow extends JFrame { private static final String TITLE = "Luyten"; private static final String DEFAULT_TAB = "#DEFAULT"; - public static Model model; private JProgressBar bar; private JLabel label; FindBox findBox; @@ -83,7 +82,6 @@ public class MainWindow extends JFrame { panel2.setPreferredSize(new Dimension(this.getWidth() / 3, 20)); panel2.add(bar); - model = new Model(this); jarsTabbedPane = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); jarsTabbedPane.setUI(new BasicTabbedPaneUI() { @Override @@ -94,7 +92,7 @@ public class MainWindow extends JFrame { return 0; } }); - jarsTabbedPane.addTab("#DEFAULT", model); + jarsTabbedPane.addTab(DEFAULT_TAB, new Model(this)); this.getContentPane().add(jarsTabbedPane); JSplitPane spt = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panel1, panel2) { @@ -118,8 +116,9 @@ public class MainWindow extends JFrame { spt.setBorder(new BevelBorder(BevelBorder.LOWERED)); spt.setPreferredSize(new Dimension(this.getWidth(), 24)); this.add(spt, BorderLayout.SOUTH); + Model jarModel = null; if (fileFromCommandLine != null) { - model.loadFile(fileFromCommandLine); + jarModel = loadNewFile(fileFromCommandLine); } try { @@ -133,11 +132,13 @@ public class MainWindow extends JFrame { fileDialog = new FileDialog(this); fileSaver = new FileSaver(bar, label); - this.setExitOnEscWhenEnabled(model); + if (jarModel != null) { + this.setExitOnEscWhenEnabled(jarModel); + } - if (fileFromCommandLine == null || fileFromCommandLine.getName().toLowerCase().endsWith(".jar") - || fileFromCommandLine.getName().toLowerCase().endsWith(".zip")) { - model.startWarmUpThread(); + if (jarModel != null && (fileFromCommandLine.getName().toLowerCase().endsWith(".jar") + || fileFromCommandLine.getName().toLowerCase().endsWith(".zip"))) { + jarModel.startWarmUpThread(); } if(RecentFiles.load() > 0) mainMenuBar.updateRecentFiles(); @@ -159,7 +160,7 @@ public class MainWindow extends JFrame { } } - public void loadNewFile(final File file) { + public Model loadNewFile(final File file) { Model jarModel = new Model(this); jarModel.loadFile(file); jarModels.add(jarModel); @@ -170,7 +171,7 @@ public class MainWindow extends JFrame { int index = jarsTabbedPane.indexOfTab(tabName); Model.Tab tabUI = new Model.Tab(tabName, new Callable() { @Override - public Void call() throws Exception { + public Void call() { int index = jarsTabbedPane.indexOfTab(tabName); jarsTabbedPane.remove(index); if (jarsTabbedPane.getTabCount() == 0) { @@ -183,6 +184,7 @@ public class MainWindow extends JFrame { if (jarsTabbedPane.indexOfTab(DEFAULT_TAB) != -1 && jarsTabbedPane.getTabCount() > 1) { removeDefaultTab(); } + return jarModel; } public void onCloseFileMenu() { From f2288cefd672d66b6a6012e769d6e2c26850d320 Mon Sep 17 00:00:00 2001 From: ATnayan Date: Sun, 5 Apr 2020 16:09:13 +0300 Subject: [PATCH 3/5] Bug fix --- src/us/deathmarine/luyten/LuytenOsx.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/us/deathmarine/luyten/LuytenOsx.java b/src/us/deathmarine/luyten/LuytenOsx.java index 1350c20..46670ae 100644 --- a/src/us/deathmarine/luyten/LuytenOsx.java +++ b/src/us/deathmarine/luyten/LuytenOsx.java @@ -16,7 +16,7 @@ public class LuytenOsx extends Luyten { Application app = new Application(); app.addApplicationListener(new ApplicationAdapter() { public void handleOpenFile(ApplicationEvent e) { - Luyten.addToPendingFiles(new File(e.getFilename())); + Luyten.openFileInInstance(new File(e.getFilename())); } public void handleQuit(ApplicationEvent e) { From ad47a934fb00d7626554176e2540977e9874df11 Mon Sep 17 00:00:00 2001 From: ATnayan Date: Sun, 5 Apr 2020 21:08:03 +0300 Subject: [PATCH 4/5] Force refresh & Bug Fix --- src/us/deathmarine/luyten/MainWindow.java | 26 ++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/us/deathmarine/luyten/MainWindow.java b/src/us/deathmarine/luyten/MainWindow.java index 4153a7e..ab89c04 100644 --- a/src/us/deathmarine/luyten/MainWindow.java +++ b/src/us/deathmarine/luyten/MainWindow.java @@ -15,10 +15,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Vector; +import java.util.*; import java.util.concurrent.Callable; import javax.swing.*; @@ -46,7 +43,7 @@ public class MainWindow extends JFrame { private FileDialog fileDialog; private FileSaver fileSaver; private JTabbedPane jarsTabbedPane; - private List jarModels; + private Map jarModels; public MainMenuBar mainMenuBar; public MainWindow(File fileFromCommandLine) { @@ -54,7 +51,7 @@ public class MainWindow extends JFrame { windowPosition = configSaver.getMainWindowPosition(); luytenPrefs = configSaver.getLuytenPreferences(); - jarModels = new ArrayList<>(); + jarModels = new HashMap(); mainMenuBar = new MainMenuBar(this); this.setJMenuBar(mainMenuBar); @@ -161,9 +158,17 @@ public class MainWindow extends JFrame { } public Model loadNewFile(final File file) { + // In case we open the same file again + // we remove the old entry to force a refresh + if (jarModels.containsKey(file.getAbsolutePath())) { + jarModels.remove(file.getAbsolutePath()); + int index = jarsTabbedPane.indexOfTab(file.getName()); + jarsTabbedPane.remove(index); + } + Model jarModel = new Model(this); jarModel.loadFile(file); - jarModels.add(jarModel); + jarModels.put(file.getAbsolutePath(), jarModel); jarsTabbedPane.addTab(file.getName(), jarModel); jarsTabbedPane.setSelectedComponent(jarModel); @@ -173,6 +178,7 @@ public class MainWindow extends JFrame { @Override public Void call() { int index = jarsTabbedPane.indexOfTab(tabName); + jarModels.remove(file.getAbsolutePath()); jarsTabbedPane.remove(index); if (jarsTabbedPane.getTabCount() == 0) { createDefaultTab(); @@ -341,20 +347,20 @@ public class MainWindow extends JFrame { } public void onThemesChanged() { - for (Model jarModel : jarModels) { + for (Model jarModel : jarModels.values()) { jarModel.changeTheme(luytenPrefs.getThemeXml()); luytenPrefs.setFont_size(jarModel.getTheme().baseFont.getSize()); } } public void onSettingsChanged() { - for (Model jarModel : jarModels) { + for (Model jarModel : jarModels.values()) { jarModel.updateOpenClasses(); } } public void onTreeSettingsChanged() { - for (Model jarModel : jarModels) { + for (Model jarModel : jarModels.values()) { jarModel.updateTree(); } } From b036b13a62467f0d23baf530d8cb0c16899cd2e0 Mon Sep 17 00:00:00 2001 From: ATnayan Date: Sun, 5 Apr 2020 21:32:39 +0300 Subject: [PATCH 5/5] [Single-Instance] Opening a jar from OS opens a tab in currently opened instance --- pom.xml | 2 +- src/us/deathmarine/luyten/Luyten.java | 77 ++++++++++++++++++++---- src/us/deathmarine/luyten/LuytenOsx.java | 3 +- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index 42f9bfe..35fb2b6 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 us.deathmarine luyten - 0.6.0 + 0.7.0 com.fifesoft diff --git a/src/us/deathmarine/luyten/Luyten.java b/src/us/deathmarine/luyten/Luyten.java index e0495d2..6c5bd7b 100644 --- a/src/us/deathmarine/luyten/Luyten.java +++ b/src/us/deathmarine/luyten/Luyten.java @@ -7,13 +7,11 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.io.*; +import java.net.ServerSocket; +import java.net.Socket; import java.net.URI; +import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; import java.util.List; import java.util.ArrayList; @@ -40,8 +38,20 @@ public class Luyten { private static final AtomicReference mainWindowRef = new AtomicReference<>(); private static final List pendingFiles = new ArrayList<>(); + private static ServerSocket lockSocket = null; - public static void main(String[] args) { + public static void main(final String[] args) { + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + try { + if (lockSocket != null) { + lockSocket.close(); + } + } catch (IOException e) { + } + } + })); try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); @@ -55,12 +65,41 @@ public class Luyten { // .zip or .jar) final File fileFromCommandLine = getFileFromCommandLine(args); + try { + launchMainInstance(fileFromCommandLine); + } catch (Exception e) { + // Instance already exists. Open new file in running instance + try { + Socket socket = new Socket("localhost", 3456); + DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); + dos.writeUTF(args[0]); + dos.flush(); + dos.close(); + socket.close(); + } catch (IOException ex) { + showExceptionDialog("Exception", e); + } + } + } + + private static void launchMainInstance(final File fileFromCommandLine) throws IOException { + lockSocket = new ServerSocket(3456); + launchSession(fileFromCommandLine); + new Thread(new Runnable() { + @Override + public void run() { + launchServer(); + } + }).start(); + } + + private static void launchSession(final File fileFromCommandLine) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (!mainWindowRef.compareAndSet(null, new MainWindow(fileFromCommandLine))) { // Already set - so add the files to open - openFileInInstance(fileFromCommandLine); + addToPendingFiles(fileFromCommandLine); } processPendingFiles(); mainWindowRef.get().setVisible(true); @@ -68,9 +107,24 @@ public class Luyten { }); } + private static void launchServer() { + try { // Server + while (true) { + Socket socket = lockSocket.accept(); + DataInputStream dis = new DataInputStream(socket.getInputStream()); + addToPendingFiles(getFileFromCommandLine(dis.readUTF())); + processPendingFiles(); + dis.close(); + socket.close(); + } + } catch (IOException e) { // Client + showExceptionDialog("Exception", e); + } + } + // Private function which processes all pending files - synchronized on the // list of pending files - private static void processPendingFiles() { + public static void processPendingFiles() { final MainWindow mainWindow = mainWindowRef.get(); if (mainWindow != null) { synchronized (pendingFiles) { @@ -84,13 +138,12 @@ public class Luyten { // Function which opens the given file in the instance, if it's running - // and if not, it processes the files - public static void openFileInInstance(File fileToOpen) { + public static void addToPendingFiles(File fileToOpen) { synchronized (pendingFiles) { if (fileToOpen != null) { pendingFiles.add(fileToOpen); } } - processPendingFiles(); } // Function which exits the application if it's running @@ -101,7 +154,7 @@ public class Luyten { } } - public static File getFileFromCommandLine(String[] args) { + public static File getFileFromCommandLine(String... args) { File fileFromCommandLine = null; try { if (args.length > 0) { diff --git a/src/us/deathmarine/luyten/LuytenOsx.java b/src/us/deathmarine/luyten/LuytenOsx.java index 46670ae..3ba653d 100644 --- a/src/us/deathmarine/luyten/LuytenOsx.java +++ b/src/us/deathmarine/luyten/LuytenOsx.java @@ -16,7 +16,8 @@ public class LuytenOsx extends Luyten { Application app = new Application(); app.addApplicationListener(new ApplicationAdapter() { public void handleOpenFile(ApplicationEvent e) { - Luyten.openFileInInstance(new File(e.getFilename())); + Luyten.addToPendingFiles(new File(e.getFilename())); + Luyten.processPendingFiles(); } public void handleQuit(ApplicationEvent e) {