Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add native open, save dlg in macOS #180

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
331 changes: 331 additions & 0 deletions app/src/main/groovy/org/jd/gui/view/MainView.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
/*
* Copyright (c) 2008-2015 Emmanuel Dupuy
* This program is made available under the terms of the GPLv3 License.
*/

package org.jd.gui.view

import groovy.swing.SwingBuilder
import org.jd.gui.Constants
import org.jd.gui.api.API
import org.jd.gui.api.feature.ContentSearchable
import org.jd.gui.api.feature.ContentSelectable
import org.jd.gui.api.feature.LineNumberNavigable
import org.jd.gui.api.feature.PageChangeListener
import org.jd.gui.api.feature.PageClosable
import org.jd.gui.api.feature.FocusedTypeGettable
import org.jd.gui.api.feature.ContentSavable
import org.jd.gui.api.feature.ContentCopyable
import org.jd.gui.api.feature.PreferencesChangeListener
import org.jd.gui.api.feature.SourcesSavable
import org.jd.gui.api.feature.UriGettable
import org.jd.gui.api.feature.UriOpenable
import org.jd.gui.model.configuration.Configuration
import org.jd.gui.model.history.History
import org.jd.gui.spi.FileLoader
import org.jd.gui.view.component.FileChooser

import javax.swing.Icon
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.event.ChangeEvent
import javax.swing.event.ChangeListener
import java.awt.Color
import java.awt.Dimension
import java.awt.Point
import javax.swing.JFileChooser
import javax.swing.JFrame
import javax.swing.JOptionPane
import javax.swing.filechooser.FileNameExtensionFilter

import org.jd.gui.view.component.IconButton
import org.jd.gui.view.component.panel.MainTabbedPanel

import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent

class MainView implements UriOpenable, PreferencesChangeListener {
SwingBuilder swing
History history
Closure openFilesClosure
Color findBackgroundColor
Color findErrorBackgroundColor

MainView(
SwingBuilder swing, Configuration configuration, API api, History history,
Closure panelClosedClosure,
Closure currentPageChangedClosure,
Closure openFilesClosure,
Closure findCriteriaChangedClosure) {
this.swing = swing
this.history = history
this.openFilesClosure = openFilesClosure

swing.edt {
// Setup
registerBeanFactory('iconButton', IconButton.class)
registerBeanFactory('mainTabbedPanel', MainTabbedPanel.class)
registerExplicitProperty('api', { api }, {}) // Used to init 'mainTabbedPanel.api'
// Load GUI description
build(MainDescription)
// Add listeners
mainTabbedPanel.pageChangedListeners.add(new PageChangeListener() {
JComponent currentPage = null

public <T extends JComponent & UriGettable> void pageChanged(T page) {
if (currentPage != page) {
// Update current page
currentPage = page
currentPageChangedClosure(page)

swing.doLater {
if (page) {
// Update title
def path = page.uri.path
int index = path.lastIndexOf('/')
def name = (index == -1) ? path : path.substring(index + 1)
mainFrame.title = name ? name + ' - Java Decompiler' : 'Java Decompiler'
// Update history
history.add(page.uri)
// Update history actions
updateHistoryActions()
// Update menu
saveAction.enabled = (page instanceof ContentSavable)
copyAction.enabled = (page instanceof ContentCopyable)
selectAllAction.enabled = (page instanceof ContentSelectable)
findAction.enabled = (page instanceof ContentSearchable)
openTypeHierarchyAction.enabled = (page instanceof FocusedTypeGettable)
goToAction.enabled = (page instanceof LineNumberNavigable)
} else {
// Update title
mainFrame.title = 'Java Decompiler'
// Update menu
saveAction.enabled = false
copyAction.enabled = false
selectAllAction.enabled = false
openTypeHierarchyAction.enabled = false
goToAction.enabled = false
}
}
}
}
})
mainTabbedPanel.tabbedPane.addChangeListener(new ChangeListener() {
int lastTabCount = 0

void stateChanged(ChangeEvent e) {
swing.with {
int tabCount = mainTabbedPanel.tabbedPane.tabCount
boolean enabled = (tabCount > 0)

closeAction.enabled = enabled
openTypeAction.enabled = enabled
searchAction.enabled = enabled
saveAllSourcesAction.enabled = (mainTabbedPanel.tabbedPane.selectedComponent instanceof SourcesSavable)

if (tabCount < lastTabCount) {
panelClosedClosure()
}

lastTabCount = tabCount
}
}
})
mainTabbedPanel.preferencesChanged(configuration.preferences)
findComboBox.editor.editorComponent.addKeyListener(new KeyAdapter() {
String lastStr = ''

void keyReleased(KeyEvent e) {
def findComboBox = swing.findComboBox

switch (e.keyCode) {
case KeyEvent.VK_ESCAPE:
swing.findPanel.visible = false
break
case KeyEvent.VK_ENTER:
def str = getFindText()
if (str.length() > 1) {
def index = findComboBox.model.getIndexOf(str)
if(index != -1 ) {
findComboBox.removeItemAt(index)
}
findComboBox.insertItemAt(str, 0)
findComboBox.selectedIndex = 0
swing.findNextAction.closure()
}
break
default:
def str = getFindText()
if (! lastStr.equals(str)) {
findCriteriaChangedClosure()
lastStr = str
}
}
}
})
findComboBox.editor.editorComponent.opaque = true

this.findBackgroundColor = findComboBox.background = findComboBox.editor.editorComponent.background
this.findErrorBackgroundColor = Color.decode(configuration.preferences.get('JdGuiPreferences.errorBackgroundColor'))
}
swing.doLater {
// Lazy initialization
new JLabel('<html>init HTML parser</html>')
}
}

void show(Point location, Dimension size, boolean maximize) {
swing.edt {
// Set position, resize and show
mainFrame.with {
setLocation(location)
setSize(size)
extendedState = maximize ? JFrame.MAXIMIZED_BOTH : 0
}
mainFrame.show()
}
}

void showFindPanel() {
swing.edt {
findPanel.visible = true
findComboBox.requestFocus()
}
}

void setFindBackgroundColor(boolean wasFound) {
swing.doLater {
findComboBox.editor.editorComponent.background = wasFound ? findBackgroundColor : findErrorBackgroundColor
}
}

JFileChooser createOpenFileChooser() {
FileChooser chooser = new FileChooser() {
void addFileFilters(Map<String, FileLoader> loaders) {
removeChoosableFileFilter(getFileFilter())

def extensions = loaders.collect({ key, value -> key }).sort()
def description = extensions.collect({ "*.$it" }).join(', ')

addChoosableFileFilter(new FileNameExtensionFilter("All files ($description)", extensions as String[]))

for (def extension : extensions) {
def loader = loaders[extension]
addChoosableFileFilter(new FileNameExtensionFilter(loader.description, loader.extensions))
}
}
void show(Closure okClosure) {
if (showOpenDialog(swing.mainFrame) == JFileChooser.APPROVE_OPTION) {
okClosure()
}
}
}
return chooser
}

JFileChooser createSaveFileChooser() {
FileChooser chooser = new FileChooser() {
void show(Closure okClosure) {
if (showSaveDialog(swing.mainFrame) == JFileChooser.APPROVE_OPTION) {
if (selectedFile.exists()) {
def title = 'Are you sure?'
def message = "The file '$selectedFile.absolutePath' already isContainsIn.\n Do you want to replace the existing file?"
if (swing.optionPane().showConfirmDialog(swing.mainFrame, message, title, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
okClosure(selectedFile)
}
} else {
okClosure(selectedFile)
}
}
}
}
return chooser
}

void showErrorDialog(String message) {
swing.optionPane().showMessageDialog(swing.mainFrame, message, 'Error', JOptionPane.ERROR_MESSAGE)
}

public <T extends JComponent & UriGettable> void addMainPanel(String title, Icon icon, String tip, T component) {
swing.edt {
swing.mainTabbedPanel.addPage(title, icon, tip, component)
}
}

public <T extends JComponent & UriGettable> List<T> getMainPanels() {
return swing.mainTabbedPanel.getPages()
}

public <T extends JComponent & UriGettable> T getSelectedMainPanel() {
return swing.mainTabbedPanel.tabbedPane.getSelectedComponent()
}

void closeCurrentTab() {
swing.doLater {
def component = mainTabbedPanel.tabbedPane.selectedComponent
if (component instanceof PageClosable) {
if (!component.closePage()) {
mainTabbedPanel.removeComponent(component)
}
} else {
mainTabbedPanel.removeComponent(component)
}
}
}

void updateRecentFilesMenu(List<File> files) {
swing.doLater {
recentFiles.removeAll()
files.each { f ->
recentFiles.add(
menuItem() {
action(name:reduceRecentFilePath(f.absolutePath), closure:{ openFilesClosure(f) })
}
)
}
}
}

String getFindText() {
def doc = swing.findComboBox.editor.editorComponent.document
return doc.getText(0, doc.length)
}

boolean getFindCaseSensitive() { swing.findCaseSensitive.isSelected() }

void updateHistoryActions() {
swing.doLater {
backwardAction.enabled = history.canBackward()
forwardAction.enabled = history.canForward()
}
}

// --- Utils --- //
static String reduceRecentFilePath(String path) {
int lastSeparatorPosition = path.lastIndexOf(File.separatorChar as int)

if ((lastSeparatorPosition == -1) || (lastSeparatorPosition < Constants.RECENT_FILE_MAX_LENGTH)) {
return path
}

int length = Constants.RECENT_FILE_MAX_LENGTH/2 - 2
String left = path.substring(0, length)
String right = path.substring(path.length() - length)

return left + "..." + right
}

// --- URIOpener --- //
boolean openUri(URI uri) {
boolean success
swing.edt {
success = swing.mainTabbedPanel.openUri(uri)
}
return success
}

// --- PreferencesChangeListener --- //
void preferencesChanged(Map<String, String> preferences) {
swing.mainTabbedPanel.preferencesChanged(preferences)
}
}
15 changes: 8 additions & 7 deletions app/src/main/java/org/jd/gui/controller/MainController.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import org.jd.gui.view.component.FileChooser;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
Expand Down Expand Up @@ -155,7 +156,7 @@ public void show(List<File> files) {
// Set drop files transfer handler
mainFrame.setTransferHandler(new FilesTransferHandler());
// Background class loading
new JFileChooser().addChoosableFileFilter(new FileNameExtensionFilter("", "dummy"));
new FileChooser().addChoosableFileFilter(new FileNameExtensionFilter("", "dummy"));
FileSystemView.getFileSystemView().isFileSystemRoot(new File("dummy"));
new JLayer();
});
Expand Down Expand Up @@ -183,7 +184,7 @@ protected void onOpen() {

String description = sb.toString();
String[] array = extensions.toArray(new String[0]);
JFileChooser chooser = new JFileChooser();
FileChooser chooser = new FileChooser();

chooser.removeChoosableFileFilter(chooser.getFileFilter());
chooser.addChoosableFileFilter(new FileNameExtensionFilter("All files (" + description + ")", array));
Expand All @@ -195,7 +196,7 @@ protected void onOpen() {

chooser.setCurrentDirectory(configuration.getRecentLoadDirectory());

if (chooser.showOpenDialog(mainView.getMainFrame()) == JFileChooser.APPROVE_OPTION) {
if (chooser.showOpenDialog(mainView.getMainFrame()) == FileChooser.APPROVE_OPTION) {
configuration.setRecentLoadDirectory(chooser.getCurrentDirectory());
openFile(chooser.getSelectedFile());
}
Expand All @@ -207,12 +208,12 @@ protected void onClose() {

protected void onSaveSource() {
if (currentPage instanceof ContentSavable) {
JFileChooser chooser = new JFileChooser();
FileChooser chooser = new FileChooser();
JFrame mainFrame = mainView.getMainFrame();

chooser.setSelectedFile(new File(configuration.getRecentSaveDirectory(), ((ContentSavable)currentPage).getFileName()));

if (chooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) {
if (chooser.showSaveDialog(mainFrame) == FileChooser.APPROVE_OPTION) {
File selectedFile = chooser.getSelectedFile();

configuration.setRecentSaveDirectory(chooser.getCurrentDirectory());
Expand Down Expand Up @@ -245,12 +246,12 @@ protected void onSaveAllSources() {

if (currentPanel instanceof SourcesSavable) {
SourcesSavable sourcesSavable = (SourcesSavable)currentPanel;
JFileChooser chooser = new JFileChooser();
FileChooser chooser = new FileChooser();
JFrame mainFrame = mainView.getMainFrame();

chooser.setSelectedFile(new File(configuration.getRecentSaveDirectory(), sourcesSavable.getSourceFileName()));

if (chooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) {
if (chooser.showSaveDialog(mainFrame) == FileChooser.APPROVE_OPTION) {
File selectedFile = chooser.getSelectedFile();

configuration.setRecentSaveDirectory(chooser.getCurrentDirectory());
Expand Down
Loading