diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java index 7555ee435b547b4f809fcd9f78688582a6730388..9b33174743db37ab0f1f0fd528e4ac0f301540c2 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java @@ -135,6 +135,9 @@ public class JadxProject { .map(TabStateViewAdapter::build) .filter(Objects::nonNull) .collect(Collectors.toList()); + if (tabStateList.isEmpty()) { + return; + } boolean dataChanged; dataChanged = data.setOpenTabs(tabStateList); dataChanged |= data.setActiveTab(activeTab); diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java index fd10b6b3bdc4b47b763266a9a24ce77c9a4c3cf7..4135ba9b2dccc717088b1008feb136018c833459 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java @@ -210,6 +210,11 @@ public class JadxSettings extends JadxCLIArgs { partialSync(settings -> settings.recentProjects = recentProjects); } + public void removeRecentProject(Path projectPath) { + recentProjects.remove(projectPath); + partialSync(settings -> settings.recentProjects = recentProjects); + } + public void saveWindowPos(Window window) { WindowLocation pos = new WindowLocation(window.getClass().getSimpleName(), window.getBounds()); windowPos.put(pos.getWindowId(), pos); diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java index 8756ba32cc8d85b84c98c7941d119dd177aff362..015861532785c957d42b26762d33b5c44be4341d 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java @@ -14,6 +14,7 @@ import jadx.api.JavaNode; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.instructions.args.ArgType; +import jadx.gui.utils.Icons; import jadx.gui.utils.OverlayIcon; import jadx.gui.utils.UiUtils; @@ -84,10 +85,10 @@ public class JMethod extends JNode { OverlayIcon overIcon = new OverlayIcon(icon); if (accessFlags.isFinal()) { - overIcon.add(UiUtils.ICON_FINAL); + overIcon.add(Icons.FINAL); } if (accessFlags.isStatic()) { - overIcon.add(UiUtils.ICON_STATIC); + overIcon.add(Icons.STATIC); } return overIcon; diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index c83552b5b9adb2592ed22a57f71f60b8a18541bf..a0eb2eb09ee9a74b5f8fbe57b6215de1f6e86186 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -125,12 +125,14 @@ import jadx.gui.ui.panel.IssuesPanel; import jadx.gui.ui.panel.JDebuggerPanel; import jadx.gui.ui.panel.ProgressPanel; import jadx.gui.ui.popupmenu.JPackagePopupMenu; +import jadx.gui.ui.treenodes.StartPageNode; import jadx.gui.ui.treenodes.SummaryNode; import jadx.gui.update.JadxUpdate; import jadx.gui.update.JadxUpdate.IUpdateCallback; import jadx.gui.update.data.Release; import jadx.gui.utils.CacheObject; import jadx.gui.utils.FontUtils; +import jadx.gui.utils.Icons; import jadx.gui.utils.LafManager; import jadx.gui.utils.Link; import jadx.gui.utils.NLS; @@ -152,7 +154,6 @@ public class MainWindow extends JFrame { private static final double WINDOW_RATIO = 1 - BORDER_RATIO * 2; public static final double SPLIT_PANE_RESIZE_WEIGHT = 0.15; - private static final ImageIcon ICON_OPEN = UiUtils.openSvgIcon("ui/openDisk"); private static final ImageIcon ICON_ADD_FILES = UiUtils.openSvgIcon("ui/addFile"); private static final ImageIcon ICON_SAVE_ALL = UiUtils.openSvgIcon("ui/menu-saveall"); private static final ImageIcon ICON_RELOAD = UiUtils.openSvgIcon("ui/refresh"); @@ -249,7 +250,7 @@ public class MainWindow extends JFrame { private void processCommandLineArgs() { if (settings.getFiles().isEmpty()) { - openFileOrProject(); + tabbedPane.showNode(new StartPageNode()); } else { open(FileUtils.fileNamesToPaths(settings.getFiles()), this::handleSelectClassOption); } @@ -286,12 +287,20 @@ public class MainWindow extends JFrame { }); } - public void openFileOrProject() { + public void openFileDialog() { + showOpenDialog(FileDialog.OpenMode.OPEN); + } + + public void openProjectDialog() { + showOpenDialog(FileDialog.OpenMode.OPEN_PROJECT); + } + + private void showOpenDialog(FileDialog.OpenMode mode) { saveAll(); if (!ensureProjectIsSaved()) { return; } - FileDialog fileDialog = new FileDialog(this, FileDialog.OpenMode.OPEN); + FileDialog fileDialog = new FileDialog(this, mode); List openPaths = fileDialog.show(); if (!openPaths.isEmpty()) { settings.setLastOpenFilePath(fileDialog.getCurrentDir()); @@ -313,6 +322,7 @@ public class MainWindow extends JFrame { } private void newProject() { + saveAll(); if (!ensureProjectIsSaved()) { return; } @@ -386,7 +396,11 @@ public class MainWindow extends JFrame { s -> update()); } - void open(List paths) { + public void open(Path path) { + open(Collections.singletonList(path), EMPTY_RUNNABLE); + } + + public void open(List paths) { open(paths, EMPTY_RUNNABLE); } @@ -825,14 +839,15 @@ public class MainWindow extends JFrame { } private void initMenuAndToolbar() { - Action openAction = new AbstractAction(NLS.str("file.open_action"), ICON_OPEN) { - @Override - public void actionPerformed(ActionEvent e) { - openFileOrProject(); - } - }; - openAction.putValue(Action.SHORT_DESCRIPTION, NLS.str("file.open_action")); - openAction.putValue(Action.ACCELERATOR_KEY, getKeyStroke(KeyEvent.VK_O, UiUtils.ctrlButton())); + ActionHandler openAction = new ActionHandler(this::openFileDialog); + openAction.setNameAndDesc(NLS.str("file.open_action")); + openAction.setIcon(Icons.OPEN); + openAction.setKeyBinding(getKeyStroke(KeyEvent.VK_O, UiUtils.ctrlButton())); + + ActionHandler openProject = new ActionHandler(this::openProjectDialog); + openProject.setNameAndDesc(NLS.str("file.open_project")); + openProject.setIcon(Icons.OPEN_PROJECT); + openProject.setKeyBinding(getKeyStroke(KeyEvent.VK_O, InputEvent.SHIFT_DOWN_MASK | UiUtils.ctrlButton())); Action addFilesAction = new AbstractAction(NLS.str("file.add_files_action"), ICON_ADD_FILES) { @Override @@ -842,7 +857,7 @@ public class MainWindow extends JFrame { }; addFilesAction.putValue(Action.SHORT_DESCRIPTION, NLS.str("file.add_files_action")); - newProjectAction = new AbstractAction(NLS.str("file.new_project")) { + newProjectAction = new AbstractAction(NLS.str("file.new_project"), Icons.NEW_PROJECT) { @Override public void actionPerformed(ActionEvent e) { newProject(); @@ -1089,6 +1104,7 @@ public class MainWindow extends JFrame { JMenu file = new JMenu(NLS.str("menu.file")); file.setMnemonic(KeyEvent.VK_F); file.add(openAction); + file.add(openProject); file.add(addFilesAction); file.addSeparator(); file.add(newProjectAction); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/TabComponent.java b/jadx-gui/src/main/java/jadx/gui/ui/TabComponent.java index 5bb7476fa99e3667ad4490320d1ec70d49225d1f..277a98f583ef7e9701d30a90bd8fedeb598e1de2 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/TabComponent.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/TabComponent.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; import javax.swing.BorderFactory; -import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JMenuItem; @@ -21,15 +20,13 @@ import javax.swing.plaf.basic.BasicButtonUI; import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JNode; import jadx.gui.ui.panel.ContentPanel; +import jadx.gui.utils.Icons; import jadx.gui.utils.NLS; import jadx.gui.utils.UiUtils; public class TabComponent extends JPanel { private static final long serialVersionUID = -8147035487543610321L; - private static final ImageIcon ICON_CLOSE = UiUtils.openSvgIcon("ui/closeHovered"); - private static final ImageIcon ICON_CLOSE_INACTIVE = UiUtils.openSvgIcon("ui/close"); - private final TabbedPane tabbedPane; private final ContentPanel contentPanel; @@ -71,8 +68,8 @@ public class TabComponent extends JPanel { label.setIcon(node.getIcon()); final JButton closeBtn = new JButton(); - closeBtn.setIcon(ICON_CLOSE_INACTIVE); - closeBtn.setRolloverIcon(ICON_CLOSE); + closeBtn.setIcon(Icons.CLOSE_INACTIVE); + closeBtn.setRolloverIcon(Icons.CLOSE); closeBtn.setRolloverEnabled(true); closeBtn.setOpaque(false); closeBtn.setUI(new BasicButtonUI()); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/dialog/FileDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/dialog/FileDialog.java index d3882d59b2084495b990a2cccf835c8c5f6624ec..425ac2c05101eb94bfa5fe3001f1e46a7ff5e52a 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/dialog/FileDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/dialog/FileDialog.java @@ -29,6 +29,7 @@ public class FileDialog { public enum OpenMode { OPEN, + OPEN_PROJECT, ADD, SAVE_PROJECT, EXPORT, @@ -95,13 +96,19 @@ public class FileDialog { private void initForMode(OpenMode mode) { switch (mode) { case OPEN: + case OPEN_PROJECT: case ADD: - fileExtList = new ArrayList<>(Arrays.asList("apk", "dex", "jar", "class", "smali", "zip", "aar", "arsc")); - if (mode == OpenMode.OPEN) { - fileExtList.addAll(Arrays.asList(JadxProject.PROJECT_EXTENSION, "aab")); + if (mode == OpenMode.OPEN_PROJECT) { + fileExtList = Collections.singletonList(JadxProject.PROJECT_EXTENSION); title = NLS.str("file.open_title"); } else { - title = NLS.str("file.add_files_action"); + fileExtList = new ArrayList<>(Arrays.asList("apk", "dex", "jar", "class", "smali", "zip", "xapk", "aar", "arsc")); + if (mode == OpenMode.OPEN) { + fileExtList.addAll(Arrays.asList(JadxProject.PROJECT_EXTENSION, "aab")); + title = NLS.str("file.open_title"); + } else { + title = NLS.str("file.add_files_action"); + } } selectionMode = JFileChooser.FILES_AND_DIRECTORIES; currentDir = mainWindow.getSettings().getLastOpenFilePath(); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/panel/StartPagePanel.java b/jadx-gui/src/main/java/jadx/gui/ui/panel/StartPagePanel.java new file mode 100644 index 0000000000000000000000000000000000000000..ad8c2675b7ea1aabb2aff275d30a74b7deb5b619 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/panel/StartPagePanel.java @@ -0,0 +1,127 @@ +package jadx.gui.ui.panel; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.nio.file.Path; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + +import jadx.gui.settings.JadxSettings; +import jadx.gui.ui.MainWindow; +import jadx.gui.ui.TabbedPane; +import jadx.gui.ui.treenodes.StartPageNode; +import jadx.gui.utils.Icons; +import jadx.gui.utils.NLS; + +public class StartPagePanel extends ContentPanel { + + public StartPagePanel(TabbedPane tabbedPane, StartPageNode node) { + super(tabbedPane, node); + MainWindow mainWindow = tabbedPane.getMainWindow(); + Font baseFont = mainWindow.getSettings().getFont(); + + JButton openFile = new JButton(NLS.str("file.open_title"), Icons.OPEN); + openFile.addActionListener(ev -> mainWindow.openFileDialog()); + + JButton openProject = new JButton(NLS.str("file.open_project"), Icons.OPEN_PROJECT); + openProject.addActionListener(ev -> mainWindow.openProjectDialog()); + + JPanel start = new JPanel(); + start.setBorder(sectionFrame(NLS.str("start_page.start"), baseFont)); + start.setLayout(new BoxLayout(start, BoxLayout.LINE_AXIS)); + start.add(openFile); + start.add(Box.createRigidArea(new Dimension(10, 0))); + start.add(openProject); + start.add(Box.createHorizontalGlue()); + + JPanel recentPanel = new JPanel(); + JScrollPane scrollPane = new JScrollPane(recentPanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setPreferredSize(new Dimension(400, 200)); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + + fillRecentPanel(recentPanel, scrollPane, mainWindow); + + JPanel recent = new JPanel(); + recent.setBorder(sectionFrame(NLS.str("start_page.recent"), baseFont)); + recent.setLayout(new BoxLayout(recent, BoxLayout.PAGE_AXIS)); + recent.add(scrollPane); + + JPanel center = new JPanel(); + center.setLayout(new BorderLayout(10, 10)); + center.add(start, BorderLayout.PAGE_START); + center.add(recent, BorderLayout.CENTER); + center.setMaximumSize(new Dimension(700, 600)); + center.setAlignmentX(CENTER_ALIGNMENT); + + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50)); + add(Box.createVerticalGlue()); + add(center); + add(Box.createVerticalGlue()); + } + + private void fillRecentPanel(JPanel panel, JScrollPane scrollPane, MainWindow mainWindow) { + JadxSettings settings = mainWindow.getSettings(); + List recentProjects = settings.getRecentProjects(); + panel.removeAll(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + Font baseFont = settings.getFont(); + Font font = baseFont.deriveFont(baseFont.getSize() - 1f); + for (Path path : recentProjects) { + JButton openBtn = new JButton(path.getFileName().toString()); + openBtn.setToolTipText(path.toAbsolutePath().toString()); + openBtn.setFont(font); + openBtn.setBorderPainted(false); + openBtn.addActionListener(ev -> mainWindow.open(path)); + + JButton removeBtn = new JButton(); + removeBtn.setIcon(Icons.CLOSE_INACTIVE); + removeBtn.setRolloverIcon(Icons.CLOSE); + removeBtn.setRolloverEnabled(true); + removeBtn.setFocusable(false); + removeBtn.setBorder(null); + removeBtn.setBorderPainted(false); + removeBtn.setContentAreaFilled(false); + removeBtn.setOpaque(true); + removeBtn.addActionListener(e -> { + mainWindow.getSettings().removeRecentProject(path); + fillRecentPanel(panel, scrollPane, mainWindow); + panel.revalidate(); + scrollPane.repaint(); + }); + JPanel linePanel = new JPanel(); + linePanel.setLayout(new BoxLayout(linePanel, BoxLayout.LINE_AXIS)); + linePanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + linePanel.add(openBtn); + linePanel.add(Box.createHorizontalGlue()); + linePanel.add(removeBtn); + + panel.add(linePanel); + } + panel.add(Box.createVerticalGlue()); + } + + private static Border sectionFrame(String title, Font font) { + TitledBorder titledBorder = BorderFactory.createTitledBorder(title); + titledBorder.setTitleFont(font.deriveFont(Font.BOLD, font.getSize() + 1)); + Border spacing = BorderFactory.createEmptyBorder(10, 10, 10, 10); + return BorderFactory.createCompoundBorder(titledBorder, spacing); + } + + @Override + public void loadSettings() { + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/ui/treenodes/StartPageNode.java b/jadx-gui/src/main/java/jadx/gui/ui/treenodes/StartPageNode.java new file mode 100644 index 0000000000000000000000000000000000000000..1bdf18c327d703cdd3117712d437b92209081d10 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/ui/treenodes/StartPageNode.java @@ -0,0 +1,35 @@ +package jadx.gui.ui.treenodes; + +import javax.swing.Icon; + +import jadx.gui.treemodel.JClass; +import jadx.gui.treemodel.JNode; +import jadx.gui.ui.TabbedPane; +import jadx.gui.ui.panel.ContentPanel; +import jadx.gui.ui.panel.StartPagePanel; +import jadx.gui.utils.Icons; +import jadx.gui.utils.NLS; + +public class StartPageNode extends JNode { + private static final long serialVersionUID = 8983134608645736174L; + + @Override + public ContentPanel getContentPanel(TabbedPane tabbedPane) { + return new StartPagePanel(tabbedPane, this); + } + + @Override + public String makeString() { + return NLS.str("start_page.title"); + } + + @Override + public Icon getIcon() { + return Icons.START_PAGE; + } + + @Override + public JClass getJParent() { + return null; + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/utils/Icons.java b/jadx-gui/src/main/java/jadx/gui/utils/Icons.java new file mode 100644 index 0000000000000000000000000000000000000000..2e31e168bcda856ca7d226c2784d12a2cb7d0aea --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/utils/Icons.java @@ -0,0 +1,20 @@ +package jadx.gui.utils; + +import javax.swing.ImageIcon; + +import static jadx.gui.utils.UiUtils.openSvgIcon; + +public class Icons { + + public static final ImageIcon OPEN = openSvgIcon("ui/openDisk"); + public static final ImageIcon OPEN_PROJECT = openSvgIcon("ui/projectDirectory"); + public static final ImageIcon NEW_PROJECT = openSvgIcon("ui/newFolder"); + + public static final ImageIcon CLOSE = openSvgIcon("ui/closeHovered"); + public static final ImageIcon CLOSE_INACTIVE = openSvgIcon("ui/close"); + + public static final ImageIcon STATIC = openSvgIcon("nodes/staticMark"); + public static final ImageIcon FINAL = openSvgIcon("nodes/finalMark"); + + public static final ImageIcon START_PAGE = openSvgIcon("nodes/newWindow"); +} diff --git a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java index cfcad549350c0bf8b3d2ffdfd94a732b24109585..5a727f055c1d737f302468e06f5a3a7cbf10c503 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java @@ -46,9 +46,6 @@ import jadx.gui.ui.codearea.AbstractCodeArea; public class UiUtils { private static final Logger LOG = LoggerFactory.getLogger(UiUtils.class); - public static final ImageIcon ICON_STATIC = openSvgIcon("nodes/staticMark"); - public static final ImageIcon ICON_FINAL = openSvgIcon("nodes/finalMark"); - /** * The minimum about of memory in bytes we are trying to keep free, otherwise the application may * run out of heap @@ -190,10 +187,10 @@ public class UiUtils { } OverlayIcon overIcon = new OverlayIcon(icon); if (af.isFinal()) { - overIcon.add(ICON_FINAL); + overIcon.add(Icons.FINAL); } if (af.isStatic()) { - overIcon.add(ICON_STATIC); + overIcon.add(Icons.STATIC); } return overIcon; } diff --git a/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java b/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java index 390a3f8d5efb4bc5acfa6569af8548b8f50f0f64..324a611bd73b5880327e20e57e069588e1215639 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/ui/ActionHandler.java @@ -11,6 +11,10 @@ public class ActionHandler extends AbstractAction { private final Consumer consumer; + public ActionHandler(Runnable action) { + this.consumer = ev -> action.run(); + } + public ActionHandler(Consumer consumer) { this.consumer = consumer; } diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index 5d4bbe8426b32dcdda8152edc1e812111162da36..89c3e4186f125f70ee09c273e655fbc334e78b4c 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -23,6 +23,7 @@ menu.update_label=Neue Version %s verfügbar! file.open_action=Datei öffnen… file.add_files_action=Dateien hinzufügen… file.open_title=Datei öffnen +#file.open_project=Open project file.new_project=Neues Projekt file.save_project=Projekt speichern file.save_project_as=Projekt speichern als… @@ -35,6 +36,10 @@ file.export_gradle=Als Gradle-Projekt speichern file.save_all_msg=Verzeichnis für das Speichern dekompilierter Ressourcen auswählen file.exit=Beenden +#start_page.title=Start page +#start_page.start=Start +#start_page.recent=Recent projects + tree.sources_title=Quelltexte tree.resources_title=Ressourcen tree.loading=Laden… diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 675c293b2fcac51b5031b962d482aebb9da9dfbe..491006c74e0dc9da154691480d52800cec05a85b 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -23,6 +23,7 @@ menu.update_label=New version %s available! file.open_action=Open files ... file.add_files_action=Add files file.open_title=Open file +file.open_project=Open project file.new_project=New project file.save_project=Save project file.save_project_as=Save project as... @@ -35,6 +36,10 @@ file.export_gradle=Save as gradle project file.save_all_msg=Select directory for save decompiled sources file.exit=Exit +start_page.title=Start page +start_page.start=Start +start_page.recent=Recent projects + tree.sources_title=Source code tree.resources_title=Resources tree.loading=Loading... diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index 0463e83e4487bbb4d63b669f6c239f196dca6d11..9af5618f0249d2b7d321bd68fa97e5d47e17465a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -23,6 +23,7 @@ menu.update_label=¡Nueva versión %s disponible! file.open_action=Abrir archivo... #file.add_files_action=Add files ... file.open_title=Abrir archivo +#file.open_project=Open project #file.new_project= #file.save_project= #file.save_project_as= @@ -35,6 +36,10 @@ file.export_gradle=Guardar como proyecto Gradle file.save_all_msg=Seleccionar carpeta para guardar fuentes descompiladas file.exit=Salir +#start_page.title=Start page +#start_page.start=Start +#start_page.recent=Recent projects + tree.sources_title=Código fuente tree.resources_title=Recursos tree.loading=Cargando... diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index 4bc2e3c065b0e703b62d2c4a75e65658322a604a..9ffb4372d3cee02a61d088a4dc9802c3794c5212 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -23,6 +23,7 @@ menu.update_label=새 버전 %s 이(가) 존재합니다! file.open_action=파일 열기 ... file.add_files_action=파일 추가 file.open_title=파일 열기 +#file.open_project=Open project file.new_project=새 프로젝트 file.save_project=프로젝트 저장 file.save_project_as=다른 이름으로 프로젝트 저장... @@ -35,6 +36,10 @@ file.export_gradle=Gradle 프로젝트로 저장 file.save_all_msg=디컴파일된 소스를 저장할 디렉토리 선택 file.exit=나가기 +#start_page.title=Start page +#start_page.start=Start +#start_page.recent=Recent projects + tree.sources_title=소스코드 tree.resources_title=리소스 tree.loading=로딩중... diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index a577f34db3ba3c5a51bfedfd786db97508eb812d..14e5ba6bf6508c484df07ed8963027c0235c59b5 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -23,6 +23,7 @@ menu.update_label=Nova versão %s disponível! file.open_action=Abrir arquivos... file.add_files_action=Adicionar arquivos file.open_title=Abrir arquivo +#file.open_project=Open project file.new_project=Novo projeto file.save_project=Salvar projeto file.save_project_as=Salvar projeto como... @@ -35,6 +36,10 @@ file.export_gradle=Salvar como um projeto gradle file.save_all_msg=Selecionar diretório para salvar arquivos descompilados file.exit=Sair +#start_page.title=Start page +#start_page.start=Start +#start_page.recent=Recent projects + tree.sources_title=Código fonte tree.resources_title=Recursos tree.loading=Carregando... diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index a0d47f1a68b945d27cf3b27cf135bec7c7367e43..82894340bcc5dfecf6c8d618f3cfe0c5cb76fb55 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -23,6 +23,7 @@ menu.update_label=发现新版本 %s! file.open_action=打开文件... file.add_files_action=添加文件 file.open_title=打开文件 +#file.open_project=Open project file.new_project=新建项目 file.save_project=保存项目 file.save_project_as=另存项目为... @@ -35,6 +36,10 @@ file.export_gradle=另存为 Gradle 项目 file.save_all_msg=请选择保存反编译资源的目录 file.exit=退出 +#start_page.title=Start page +#start_page.start=Start +#start_page.recent=Recent projects + tree.sources_title=源代码 tree.resources_title=资源文件 tree.loading=加载中... diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index 9c47895a98698a10aacf33bd93c2903e75577ac7..d1ee8bd09c6f32e3d464838054234d98793d525a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -23,6 +23,7 @@ menu.update_label=新版本 %s 可供下載! file.open_action=開啟檔案... file.add_files_action=新增檔案 file.open_title=開啟檔案 +#file.open_project=Open project file.new_project=新建專案 file.save_project=儲存專案 file.save_project_as=另存專案... @@ -35,6 +36,10 @@ file.export_gradle=另存為 gradle 專案 file.save_all_msg=選擇儲存反編譯原始碼的路徑 file.exit=離開 +#start_page.title=Start page +#start_page.start=Start +#start_page.recent=Recent projects + tree.sources_title=原始碼 tree.resources_title=資源 tree.loading=載入中... diff --git a/jadx-gui/src/main/resources/icons/nodes/newWindow.svg b/jadx-gui/src/main/resources/icons/nodes/newWindow.svg new file mode 100644 index 0000000000000000000000000000000000000000..8dfd122b4e888b620c1825f33e85d82bff8bc37b --- /dev/null +++ b/jadx-gui/src/main/resources/icons/nodes/newWindow.svg @@ -0,0 +1,4 @@ + + + + diff --git a/jadx-gui/src/main/resources/icons/ui/newFolder.svg b/jadx-gui/src/main/resources/icons/ui/newFolder.svg new file mode 100644 index 0000000000000000000000000000000000000000..6f94976070be139f6c45395d1d5349495742b695 --- /dev/null +++ b/jadx-gui/src/main/resources/icons/ui/newFolder.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/jadx-gui/src/main/resources/icons/ui/projectDirectory.svg b/jadx-gui/src/main/resources/icons/ui/projectDirectory.svg new file mode 100644 index 0000000000000000000000000000000000000000..6e98f412401898f5c5bc7b8970f01ce228b5dbea --- /dev/null +++ b/jadx-gui/src/main/resources/icons/ui/projectDirectory.svg @@ -0,0 +1,7 @@ + + + + + + +