2021-06-26 01:13:46 +00:00
|
|
|
package the.bytecode.club.bytecodeviewer.gui.resourceviewer;
|
|
|
|
|
2021-08-26 21:59:07 +00:00
|
|
|
import java.awt.BorderLayout;
|
|
|
|
import java.awt.Component;
|
|
|
|
import java.awt.FlowLayout;
|
|
|
|
import java.awt.Rectangle;
|
2021-06-26 01:13:46 +00:00
|
|
|
import java.awt.event.MouseEvent;
|
|
|
|
import java.awt.event.MouseListener;
|
2021-06-26 14:52:28 +00:00
|
|
|
import java.util.HashSet;
|
2021-08-27 08:49:31 +00:00
|
|
|
import java.util.Set;
|
2021-08-26 21:59:07 +00:00
|
|
|
import javax.swing.JButton;
|
|
|
|
import javax.swing.JMenuItem;
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
import javax.swing.JPopupMenu;
|
|
|
|
import javax.swing.JTabbedPane;
|
2021-06-26 01:13:46 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
2021-07-21 14:18:33 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
2021-06-26 01:13:46 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
|
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.FileViewer;
|
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
2021-08-26 21:59:07 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
2021-07-21 13:54:29 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.translation.TranslatedComponents;
|
2021-07-21 14:18:33 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
2021-07-07 10:39:29 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJButton;
|
|
|
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedVisibleComponent;
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
import static the.bytecode.club.bytecodeviewer.Constants.BLOCK_TAB_MENU;
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
|
|
|
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
|
|
|
|
* *
|
|
|
|
* 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 *
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The pane that contains all of the resources as tabs.
|
|
|
|
*
|
|
|
|
* @author Konloch
|
|
|
|
* @author WaterWolf
|
2021-07-04 07:04:08 +00:00
|
|
|
* @since 09/26/2011
|
2021-06-26 01:13:46 +00:00
|
|
|
*/
|
2021-07-16 03:50:05 +00:00
|
|
|
|
|
|
|
public class Workspace extends TranslatedVisibleComponent
|
2021-06-26 01:13:46 +00:00
|
|
|
{
|
|
|
|
public final JTabbedPane tabs;
|
|
|
|
public final JPanel buttonPanel;
|
|
|
|
public final JButton refreshClass;
|
2021-08-27 08:49:31 +00:00
|
|
|
public final Set<String> openedTabs = new HashSet<>();
|
2021-06-26 01:13:46 +00:00
|
|
|
|
2021-07-16 03:50:05 +00:00
|
|
|
public Workspace()
|
2021-06-26 01:13:46 +00:00
|
|
|
{
|
2021-07-21 13:54:29 +00:00
|
|
|
super("Workspace", TranslatedComponents.WORK_SPACE);
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
this.tabs = new JTabbedPane();
|
|
|
|
|
|
|
|
JPopupMenu popUp = new JPopupMenu();
|
|
|
|
JMenuItem closeAllTabs = new JMenuItem("Close All But This");
|
|
|
|
JMenuItem closeTab = new JMenuItem("Close Tab");
|
|
|
|
closeTab.addActionListener(e ->
|
|
|
|
{
|
2021-06-26 02:11:43 +00:00
|
|
|
TabExitButton tabExitButton = (TabExitButton) ((JPopupMenu)((JMenuItem) e.getSource()).getParent()).getInvoker();
|
|
|
|
final int index = tabExitButton.getTabIndex();
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
if (index != -1)
|
|
|
|
tabs.remove(index);
|
|
|
|
});
|
2021-07-30 02:32:32 +00:00
|
|
|
|
2021-06-26 01:13:46 +00:00
|
|
|
closeAllTabs.addActionListener(e ->
|
|
|
|
{
|
2021-06-26 02:11:43 +00:00
|
|
|
TabExitButton tabExitButton = (TabExitButton) ((JPopupMenu)((JMenuItem) e.getSource()).getParent()).getInvoker();
|
|
|
|
final int index = tabExitButton.getTabIndex();
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (tabs.getTabCount() <= 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (index != 0)
|
|
|
|
tabs.remove(0);
|
|
|
|
else
|
|
|
|
tabs.remove(1);
|
|
|
|
}
|
|
|
|
});
|
2021-07-07 10:39:29 +00:00
|
|
|
|
2021-06-26 01:13:46 +00:00
|
|
|
tabs.addMouseListener(new MouseListener()
|
|
|
|
{
|
|
|
|
@Override
|
|
|
|
public void mouseClicked(MouseEvent e) { }
|
|
|
|
@Override
|
|
|
|
public void mouseEntered(MouseEvent arg0) { }
|
|
|
|
@Override
|
|
|
|
public void mouseExited(MouseEvent arg0) { }
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void mousePressed(MouseEvent e)
|
|
|
|
{
|
|
|
|
if (BLOCK_TAB_MENU)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (e.getButton() == 3)
|
|
|
|
{
|
|
|
|
Rectangle bounds = new Rectangle(1, 1, e.getX(), e.getY());
|
|
|
|
|
|
|
|
for (int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
|
|
|
|
{
|
|
|
|
Component c = BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i);
|
|
|
|
if (c != null && bounds.intersects(c.getBounds()))
|
|
|
|
{
|
|
|
|
popUp.setVisible(true);
|
2021-12-19 23:24:17 +00:00
|
|
|
closeAllTabs.setText(TranslatedStrings.CLOSE_TAB + ": " + ((TabbedPane) c).tabName);
|
|
|
|
closeTab.setText(TranslatedStrings.CLOSE_TAB + ": " + ((TabbedPane) c).tabName);
|
2021-06-26 01:13:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
popUp.setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void mouseReleased(MouseEvent e) { }
|
|
|
|
});
|
|
|
|
|
|
|
|
popUp.add(closeAllTabs);
|
|
|
|
popUp.add(closeTab);
|
|
|
|
|
|
|
|
if (!BLOCK_TAB_MENU)
|
|
|
|
tabs.setComponentPopupMenu(popUp);
|
|
|
|
|
|
|
|
getContentPane().setLayout(new BorderLayout());
|
|
|
|
getContentPane().add(tabs, BorderLayout.CENTER);
|
|
|
|
|
|
|
|
buttonPanel = new JPanel(new FlowLayout());
|
|
|
|
|
2021-07-21 13:54:29 +00:00
|
|
|
refreshClass = new TranslatedJButton("Refresh", TranslatedComponents.REFRESH);
|
2021-07-07 10:39:29 +00:00
|
|
|
refreshClass.addActionListener((event)->
|
|
|
|
{
|
2021-07-05 02:36:31 +00:00
|
|
|
refreshClass.setEnabled(false);
|
2021-07-16 03:50:05 +00:00
|
|
|
Thread t = new Thread(() -> new WorkspaceRefresh(event).run(), "Refresh");
|
2021-06-26 01:13:46 +00:00
|
|
|
t.start();
|
|
|
|
});
|
|
|
|
|
|
|
|
buttonPanel.add(refreshClass);
|
|
|
|
buttonPanel.setVisible(false);
|
2021-07-07 10:39:29 +00:00
|
|
|
|
2021-06-26 01:13:46 +00:00
|
|
|
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
tabs.addContainerListener(new TabRemovalEvent());
|
|
|
|
tabs.addChangeListener(arg0 -> buttonPanel.setVisible(tabs.getSelectedIndex() != -1));
|
|
|
|
|
|
|
|
this.setVisible(true);
|
|
|
|
}
|
|
|
|
|
2021-06-26 12:15:53 +00:00
|
|
|
//load class resources
|
2021-07-14 11:58:35 +00:00
|
|
|
public void addClassResource(final ResourceContainer container, final String name)
|
2021-06-26 01:13:46 +00:00
|
|
|
{
|
2021-07-14 11:58:35 +00:00
|
|
|
addResource(container, name, new ClassViewer(container, name));
|
2021-06-26 01:13:46 +00:00
|
|
|
}
|
|
|
|
|
2021-06-26 12:15:53 +00:00
|
|
|
//Load file resources
|
2021-07-14 11:58:35 +00:00
|
|
|
public void addFileResource(final ResourceContainer container, final String name)
|
2021-06-26 01:13:46 +00:00
|
|
|
{
|
2021-07-14 11:58:35 +00:00
|
|
|
addResource(container, name, new FileViewer(container, name));
|
2021-06-26 12:33:42 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 08:44:37 +00:00
|
|
|
private void addResource(final ResourceContainer container, final String name, final ResourceViewer resourceView)
|
2021-06-26 12:33:42 +00:00
|
|
|
{
|
2021-07-21 14:18:33 +00:00
|
|
|
// Warn user and prevent 'nothing' from opening if no Decompiler is selected
|
|
|
|
if(BytecodeViewer.viewer.viewPane1.getSelectedDecompiler() == Decompiler.NONE &&
|
|
|
|
BytecodeViewer.viewer.viewPane2.getSelectedDecompiler() == Decompiler.NONE &&
|
|
|
|
BytecodeViewer.viewer.viewPane3.getSelectedDecompiler() == Decompiler.NONE)
|
|
|
|
{
|
|
|
|
BytecodeViewer.showMessage(TranslatedStrings.SUGGESTED_FIX_NO_DECOMPILER_WARNING.toString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-21 20:11:46 +00:00
|
|
|
//unlock the refresh button
|
|
|
|
BytecodeViewer.viewer.workPane.refreshClass.setEnabled(true);
|
2021-07-21 14:18:33 +00:00
|
|
|
|
2021-07-11 08:44:37 +00:00
|
|
|
final String workingName = container.getWorkingName(name);
|
2021-06-29 11:12:49 +00:00
|
|
|
|
2021-06-26 14:52:28 +00:00
|
|
|
//create a new tab if the resource isn't opened currently
|
|
|
|
if (!openedTabs.contains(workingName))
|
2021-06-26 01:13:46 +00:00
|
|
|
{
|
2021-07-23 22:12:53 +00:00
|
|
|
addResourceToTab(resourceView, workingName, container.name, name);
|
2021-06-26 01:13:46 +00:00
|
|
|
}
|
2021-07-16 03:50:05 +00:00
|
|
|
else //if the resource is already opened select this tab as the active one
|
2021-06-26 01:13:46 +00:00
|
|
|
{
|
2021-07-16 03:50:05 +00:00
|
|
|
//TODO openedTabs could be changed to a HashMap<String, Integer> for faster lookups
|
|
|
|
|
|
|
|
//search through each tab
|
2021-06-26 14:52:28 +00:00
|
|
|
for(int i = 0; i < tabs.getTabCount(); i++)
|
|
|
|
{
|
2021-07-16 03:50:05 +00:00
|
|
|
//find the matching resource and open it
|
2021-06-26 14:52:28 +00:00
|
|
|
ResourceViewer tab = ((TabbedPane)tabs.getTabComponentAt(i)).resource;
|
2021-07-14 11:58:35 +00:00
|
|
|
if(tab.resource.workingName.equals(workingName))
|
2021-06-26 14:52:28 +00:00
|
|
|
{
|
|
|
|
tabs.setSelectedIndex(i);
|
|
|
|
break;
|
|
|
|
}
|
2021-06-26 01:13:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-07-23 22:12:53 +00:00
|
|
|
|
|
|
|
public void addResourceToTab(ResourceViewer resourceView, String workingName, String containerName, String name)
|
|
|
|
{
|
|
|
|
//start processing the resource to be viewed
|
|
|
|
if(resourceView instanceof ClassViewer)
|
|
|
|
resourceView.refresh(null);
|
|
|
|
|
|
|
|
//add the resource view to the tabs
|
|
|
|
tabs.add(resourceView);
|
|
|
|
|
|
|
|
//get the resource view index
|
|
|
|
final int tabIndex = tabs.indexOfComponent(resourceView);
|
|
|
|
|
|
|
|
//create a new tabbed pane
|
|
|
|
TabbedPane tabbedPane = new TabbedPane(tabIndex, workingName, containerName, name, tabs, resourceView);
|
|
|
|
resourceView.tabbedPane = tabbedPane;
|
|
|
|
resourceView.resource.workingName = workingName;
|
|
|
|
|
|
|
|
//set the tabs index
|
|
|
|
tabs.setTabComponentAt(tabIndex, tabbedPane);
|
|
|
|
|
|
|
|
//open the tab that was just added
|
|
|
|
tabs.setSelectedIndex(tabIndex);
|
|
|
|
|
|
|
|
//set resource as opened in a tab
|
|
|
|
openedTabs.add(workingName);
|
|
|
|
|
|
|
|
//refresh the tab title
|
|
|
|
resourceView.refreshTitle();
|
|
|
|
}
|
2021-06-26 01:13:46 +00:00
|
|
|
|
2021-07-07 03:05:35 +00:00
|
|
|
public ResourceViewer getActiveResource() {
|
2021-06-26 01:13:46 +00:00
|
|
|
return (ResourceViewer) tabs.getSelectedComponent();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Component[] getLoadedViewers() {
|
|
|
|
return tabs.getComponents();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void resetWorkspace()
|
|
|
|
{
|
|
|
|
tabs.removeAll();
|
|
|
|
tabs.updateUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static final long serialVersionUID = 6542337997679487946L;
|
2021-08-26 21:59:07 +00:00
|
|
|
}
|