diff --git a/DESCRIPTION b/DESCRIPTION index 2082bac..e5b2ea3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,16 +1,24 @@ Package: rChoiceDialogs Type: Package Title: rChoiceDialogs collection -Version: 1.0.4 -Date: 2012-10-11 -Author: Alex Lisovich, Roger Day -Maintainer: Alex Lisovich +Version: 1.0.6 +Date: 2014-09-05 +Authors@R: c(person("Alex","Lisovich",role=c("aut","cre"),email="alex.lisovich@gmail.com"), + person("Roger","Day",role="aut",email="day01@pitt.edu"), + person("Sun Microsystems, Inc",role="cph", + comment="swing-layout-1.0.4.jar, download from http://www.java2s.com/Code/Jar/s/Downloadswinglayout104jar.htm")) Description: Collection of portable choice dialog widgets -License: GPL (>= 2.0) +License: LGPL (>= 2.1) Depends: rJava, utils Imports: tcltk Collate: 'zzz.R' 'rChoiceDialogs-package.R' 'rFileChooser.R' 'rListChooser.R' 'rMiscFunctions.R' -Packaged: 2012-10-11 23:51:04 UTC; alex +Packaged: 2014-09-10 20:49:54 UTC; alex +Author: Alex Lisovich [aut, cre], + Roger Day [aut], + Sun Microsystems, Inc [cph] (swing-layout-1.0.4.jar, download from + http://www.java2s.com/Code/Jar/s/Downloadswinglayout104jar.htm) +Maintainer: Alex Lisovich +NeedsCompilation: no Repository: CRAN -Date/Publication: 2012-10-12 05:41:04 +Date/Publication: 2014-09-11 07:26:55 diff --git a/MD5 b/MD5 index be66776..1dc6d6e 100644 --- a/MD5 +++ b/MD5 @@ -1,14 +1,20 @@ -b886f8996805da436cb59013fd1cf9da *DESCRIPTION -ff553020f13742c7b65afc887b73bcf2 *NAMESPACE +1e351c4bce4ea006b6cb4d61a70e7c3c *DESCRIPTION +a99f53102595de313fb3247aa4ecd8e2 *NAMESPACE 4795879463cc66dc276105f9a1922876 *R/rChoiceDialogs-package.R f2765d70815d60b73acad89ef1cd87f0 *R/rFileChooser.R cca0d857e9d12d4b44ae236ef7791e93 *R/rListChooser.R 08ad09d62f4278740b2f25018c97b675 *R/rMiscFunctions.R dd30f59298045dc8311b37c9d4c79bc4 *R/zzz.R -28b08c9aaad61c57cb9bf79c2ddaf7a5 *inst/doc/rChoiceDialogs.Rnw +a7d87b428a70389de29ce7a0f0407c44 *build/vignette.rds +b9b666b24027fe08035c5eef045d0852 *inst/doc/rChoiceDialogs.R +599e3ab709d3946ff61cacdd8d64065d *inst/doc/rChoiceDialogs.Rnw d920b83dd6e65aabfc88b21d90b7906c *inst/doc/rChoiceDialogs.pdf b2eb31eeaf1d5cc0e9855d1b65d14f96 *inst/java/rJavaUtils.jar 983f446152a79d2985a31ae6ad9fd97a *inst/java/swing-layout-1.0.4.jar +2613041a000afd8d6494e16934eb5fe7 *java/ExtensionFileFilter.java +b592c5d3309d34dfb6cd05c49ca85795 *java/Main.java +b278000f7d1fab13d875e5fbc136b0f2 *java/rJavaFileChooser.java +babbe91b7ad1058495f732900deef168 *java/rJavaListChooser.java 42f89495fae7812a866573e82b95f12a *man/canUseJava.Rd 3c2cca5211cef077baad1af8e7ad53c9 *man/canUseJavaModal.Rd 461cb8bdd5282946cc7ed2f299fbb043 *man/canUseTclTk.Rd @@ -22,3 +28,4 @@ fd0a938f80dc02b1fb56f9fad29663c5 *man/jselect.list.Rd 694fed83cad837e1d27f8d00b81b1c56 *man/rchoose.files.Rd 0f65c83e2cb98e3115c2fc597ce5ccbb *man/rselect.list.Rd 5ab55de81f706c88045a21ad30ac274b *man/tkchoose.files.Rd +599e3ab709d3946ff61cacdd8d64065d *vignettes/rChoiceDialogs.Rnw diff --git a/NAMESPACE b/NAMESPACE index 6d03820..dc69dc1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,3 +1,5 @@ +import( + rJava) export( canUseJava, canUseJavaModal, diff --git a/build/vignette.rds b/build/vignette.rds new file mode 100644 index 0000000..d0611d0 Binary files /dev/null and b/build/vignette.rds differ diff --git a/inst/doc/rChoiceDialogs.R b/inst/doc/rChoiceDialogs.R new file mode 100644 index 0000000..c17f6e5 --- /dev/null +++ b/inst/doc/rChoiceDialogs.R @@ -0,0 +1,13 @@ +### R code from vignette source 'rChoiceDialogs.Rnw' +### Encoding: UTF-8 + +################################################### +### code chunk number 1: sessionInfo +################################################### + +library(rChoiceDialogs) + +toLatex(sessionInfo()) + + + diff --git a/inst/doc/rChoiceDialogs.Rnw b/inst/doc/rChoiceDialogs.Rnw index 274daf4..7df3473 100644 --- a/inst/doc/rChoiceDialogs.Rnw +++ b/inst/doc/rChoiceDialogs.Rnw @@ -55,7 +55,7 @@ lists, files and folders} \author{Alex Lisovich$^{\text{1}}$, Roger Day$^{\text{1,2}}$} -\date{October 6, 2012} +\date{September 6, 2012} \maketitle diff --git a/java/ExtensionFileFilter.java b/java/ExtensionFileFilter.java new file mode 100644 index 0000000..1978637 --- /dev/null +++ b/java/ExtensionFileFilter.java @@ -0,0 +1,53 @@ +package rjavautils; + +import java.io.File; +import javax.swing.filechooser.FileFilter; + +class ExtensionFileFilter extends FileFilter +{ + String description; + String[] extensions; + + public ExtensionFileFilter(String description, String extension) + { + this(description, new String[] { extension }); + } + + public ExtensionFileFilter(String description, String[] extensions) + { + if (description == null) + this.description = (extensions[0] + "{ " + extensions.length + "} "); + else { + this.description = description; + } + this.extensions = ((String[])(String[])extensions.clone()); + toLower(this.extensions); + } + + private void toLower(String[] array) { + int i = 0; for (int n = array.length; i < n; i++) + array[i] = array[i].toLowerCase(); + } + + public String getDescription() + { + return this.description; + } + + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + String path = file.getAbsolutePath().toLowerCase(); + int i = 0; for (int n = this.extensions.length; i < n; i++) { + String extension = this.extensions[i]; + if (extension.equals("*")) + return true; + if ((path.endsWith(extension)) && (path.charAt(path.length() - extension.length() - 1) == '.')) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/java/Main.java b/java/Main.java new file mode 100644 index 0000000..7abfb6a --- /dev/null +++ b/java/Main.java @@ -0,0 +1,24 @@ +package rjavautils; + +import javax.swing.SwingUtilities; + +public class Main +{ + public static void main(String[] args) + { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + //rJavaFileChooser fc = new rJavaFileChooser(); + //fc.setMultiSelectionEnabled(true); + //int res = fc.showOpenDialog(null, true); + String [] choice={"one","two","three","four"}; + rJavaListChooser lc= new rJavaListChooser(null,true); + lc.setMultipleSelection(true); + lc.setTitle("test"); + + lc.setSelectionValues(choice); + String [] res=lc.showDialog(); + } + }); + } +} \ No newline at end of file diff --git a/java/rJavaFileChooser.java b/java/rJavaFileChooser.java new file mode 100644 index 0000000..1aa6e58 --- /dev/null +++ b/java/rJavaFileChooser.java @@ -0,0 +1,74 @@ +package rjavautils; + +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.HeadlessException; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; + +public class rJavaFileChooser extends JFileChooser +{ + JDialog parent; + int retVal; + + protected void closeDialog() + { + if (this.parent.isModal()) { + WindowEvent wev = new WindowEvent(this.parent, 201); + Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev); + } else { + this.parent.setVisible(false); + } + } + + public int showOpenDialog(Frame owner, boolean Modal) throws HeadlessException + { + this.retVal = 1; + + this.parent = new JDialog(owner, getDialogTitle(), Modal); + + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("ApproveSelection")) { + rJavaFileChooser.this.retVal = 0; + rJavaFileChooser.this.closeDialog(); + } else if (e.getActionCommand().equals("CancelSelection")) { + rJavaFileChooser.this.closeDialog(); + } + } + }); + if (this.parent.isModal()) + this.parent.setDefaultCloseOperation(2); + else { + this.parent.setDefaultCloseOperation(1); + } + + this.parent.getContentPane().add(this); + + this.parent.pack(); + this.parent.setLocationRelativeTo(null); + this.parent.setAlwaysOnTop(true); + this.parent.setVisible(true); + + return this.retVal; + } + + public void dispose() { + this.parent.setDefaultCloseOperation(2); + WindowEvent wev = new WindowEvent(this.parent, 201); + Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev); + } + + public boolean isRunning() { + return this.parent.isVisible(); + } + + public boolean selectionApproved() { + return this.retVal == 0; + } +} \ No newline at end of file diff --git a/java/rJavaListChooser.java b/java/rJavaListChooser.java new file mode 100644 index 0000000..48ae184 --- /dev/null +++ b/java/rJavaListChooser.java @@ -0,0 +1,157 @@ +package rjavautils; + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; +import org.jdesktop.layout.GroupLayout; + +public class rJavaListChooser extends JDialog +{ + String[] m_Selection; + int[] m_initialSelection; + boolean m_bMultiple; + String[] m_sItems; + DefaultListModel m_listModel; + private JButton cancelButton; + private JList itemList; + private JScrollPane jScrollPane1; + private JButton okButton; + + public rJavaListChooser(Frame parent, boolean modal) + { + super(parent, modal); + this.m_listModel = new DefaultListModel(); + this.m_sItems = new String[0]; + this.m_initialSelection = new int[0]; + } + + protected void initSelectionValues() { + this.m_listModel.clear(); + for (int i = 0; i < this.m_sItems.length; i++) { + this.m_listModel.addElement(this.m_sItems[i]); + } + this.itemList.setModel(this.m_listModel); + this.itemList.setSelectedIndices(this.m_initialSelection); + } + + protected void initSize() { + setMinimumSize(getPreferredSize()); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + Dimension dlgSize = getSize(); + Dimension listSize = this.itemList.getSize(); + Dimension listPreferredSize = this.itemList.getPreferredSize(); + dlgSize.setSize(dlgSize.width + listPreferredSize.width - listSize.width, dlgSize.height + listPreferredSize.height - listSize.height); + + double width = Math.min(0.8D * screenSize.width, dlgSize.width); + double height = Math.min(0.8D * screenSize.height, dlgSize.height); + + setSize((int)Math.round(width), (int)Math.round(height)); + } + + public void setSelectionValues(String[] sItems) + { + this.m_sItems = sItems; + } + + public void setInitialSelection(int[] initialSelection) { + this.m_initialSelection = initialSelection; + } + + public void setMultipleSelection(boolean bMultiple) { + this.m_bMultiple = bMultiple; + } + + public String[] getSelection() { + return this.m_Selection; + } + public String[] showDialog() { + this.m_Selection = new String[0]; + + initComponents(); + this.itemList.setSelectionMode(this.m_bMultiple ? 2 : 0); + + initSelectionValues(); + initSize(); + setLocationRelativeTo(null); + setAlwaysOnTop(true); + setVisible(true); + return this.m_Selection; + } + + public boolean isRunning() { + return isVisible(); + } + + private void initComponents() + { + this.cancelButton = new JButton(); + this.okButton = new JButton(); + this.jScrollPane1 = new JScrollPane(); + this.itemList = new JList(); + + setDefaultCloseOperation(2); + + this.cancelButton.setText("Cancel"); + this.cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + rJavaListChooser.this.cancelButtonActionPerformed(evt); + } + }); + this.okButton.setText("OK"); + this.okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + rJavaListChooser.this.okButtonActionPerformed(evt); + } + }); + this.jScrollPane1.setViewportView(this.itemList); + + GroupLayout layout = new GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(1).add(layout.createSequentialGroup().addContainerGap().add(layout.createParallelGroup(1).add(2, layout.createSequentialGroup().add(this.okButton, -2, 69, -2).addPreferredGap(1).add(this.cancelButton)).add(this.jScrollPane1, -1, 146, 32767)).addContainerGap())); + + layout.setVerticalGroup(layout.createParallelGroup(1).add(2, layout.createSequentialGroup().addContainerGap().add(this.jScrollPane1, -1, 37, 32767).addPreferredGap(1).add(layout.createParallelGroup(3).add(this.cancelButton).add(this.okButton)).addContainerGap())); + + pack(); + } + + private void okButtonActionPerformed(ActionEvent evt) { + Object[] selection = this.itemList.getSelectedValues(); + this.m_Selection = new String[selection.length]; + for (int i = 0; i < selection.length; i++) { + this.m_Selection[i] = ((String)selection[i]); + } + dispose(); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + dispose(); + } + + public static void main(String[] args) + { + EventQueue.invokeLater(new Runnable() { + public void run() { + rJavaListChooser dialog = new rJavaListChooser(new JFrame(), true); + dialog.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + dialog.setVisible(true); + } + }); + } +} \ No newline at end of file diff --git a/vignettes/rChoiceDialogs.Rnw b/vignettes/rChoiceDialogs.Rnw new file mode 100644 index 0000000..7df3473 --- /dev/null +++ b/vignettes/rChoiceDialogs.Rnw @@ -0,0 +1,185 @@ +%% LyX 2.0.2 created this file. For more info, see http://www.lyx.org/. +%% Do not edit unless you really know what you are doing. +\documentclass[english]{article} +\usepackage[T1]{fontenc} +\usepackage[latin9]{inputenc} +\usepackage{url} +\usepackage{amstext} + +\makeatletter + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands. +%% Because html converters don't know tabularnewline +\providecommand{\tabularnewline}{\\} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands. +%\usepackage{Sweave} +\ifdefined\Sinput +\else + \RequirePackage[nogin]{Sweave} +\fi +\usepackage{tikz} +\newenvironment{dummy}{\par}{\par} +\newcommand{\lyxaddress}[1]{ +\par {\raggedright #1 +\vspace{1.4em} +\noindent\par} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. +\newcommand{\Rcode}[1]{{\texttt{#1}}} +\newcommand{\Robject}[1]{{\texttt{#1}}} +\newcommand{\Rcommand}[1]{{\texttt{#1}}} +\newcommand{\Rfunction}[1]{{\texttt{#1}}} +\newcommand{\Rfunarg}[1]{{\textit{#1}}} +\newcommand{\Rpackage}[1]{{\textit{#1}}} +\newcommand{\Rmethod}[1]{{\textit{#1}}} +\newcommand{\Rclass}[1]{{\textit{#1}}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands. +% Meta information - fill between {} and do not remove % +% \VignetteIndexEntry{Simple cross-platform dialogs for lists, files and folders. } +% \VignetteDepends{rJava, utils} +% \VignetteKeywords{} +% \VignettePackage{rChoiceDialogs} + +\makeatother + +\usepackage{babel} +\begin{document} + +\title{The rChoiceDialogs package: \newline Cross-platform dialogs for +lists, files and folders} + + +\author{Alex Lisovich$^{\text{1}}$, Roger Day$^{\text{1,2}}$} + + +\date{September 6, 2012} + +\maketitle + +\lyxaddress{$^{\text{1}}$Department of Biomedical Informatics, $^{\text{2}}$Department +of Biostatistics \newline University of Pittsburgh} + + +\section{Overview} + +The rChoiceDialogs package provides a single mechanism for multiple-selection +choice dialogs with acceptable modal-window behavior. + +The motivating use case was the need for a cross-platform File Open +dialog supporting multiple selections. On Windows, \Rfunction{utils::choose.files()} +can cause confusion by disappearing behind other windows. In addition, +on Mac OS X and Linux this is unavailable. Another approach is \Rfunction{tcltk::choose.files()}. +While the tcltk package comes with a standard installation on Mac +OS X, its availability on Linux depends on an option selected during +the R installation. Another deficiency of the tcltk solution is that +modal dialogs tend to disappear under other windows. The third approach, +a Java-based solution, using for example the rJava package{[}1{]}, +should work for systems with Java installed, but there are complications +with the operating system Mac OS X. Apple ships its own Java implementation +which Apple ships with Mac OS X, causing difficulties for rJava. The +Mac OS X user can also install a generic Java from SUN, but this entails +additional complications. + +This package attempts to overcome these deficiencies. Wrapper functions +make the best choice among the three approaches in the previous paragraph, +and dispatch the appropriate function calls. They also achieve uniformity +in the argument lists (signatures). + +The package rChoiceDialogs is used in IdMappingRetrieval and IdMappingAnalysis, +which address problems related to ID mapping, data collection and +analysis in bioinformatics, also developed by our group. + + +\section{Usage} + +Currently the package supports the general-purpose multiple-choice +widget \Rfunction{rselect.list()}, and two special-purpose widgets: +\Rfunction{rchoose.dir()} for choosing a directory, and \Rfunction{rchoose.files()} +for choosing multiple files. Each of these functions utilizes \Rfunction{canUseJava()} +and \Rfunction{canUseTclTk()} to determine suitability of the corresponding +graphics dispatch mechanism. (The Java branch is the first choice +when it is suitable.) . When neither available the command line based +option utilized. +\begin{itemize} +\item For \Rfunction{rselect.list()}, the dispatch proceeds as follows: +\end{itemize} +\begin{tabular}{|c|c|} +\hline + & \Rfunction{rselect.list()}\tabularnewline +\hline +\hline +JAVA & \Rfunction{rChoiceDialogs::jselect.list()}\tabularnewline +\hline +Windows, or OS X with Aqua graphics & \Rfunction{utils::select.list()}\tabularnewline +\hline +TCL/TK & \Rfunction{tcltk::tk\_select.list()}\tabularnewline +\hline +none available & \Rfunction{select.list()}\tabularnewline +\hline +\end{tabular} +\begin{itemize} +\item For \Rfunction{rchoose.dir()}, the dispatch proceeds as follows: +\end{itemize} +\begin{tabular}{|c|c|} +\hline + & \Rfunction{rchoose.dir()}\tabularnewline +\hline +\hline +JAVA & \Rfunction{rChoiceDialogs::jchoose.dir()}\tabularnewline +\hline +TCL/TK & \Rfunction{tcltk::tk\_choose.dir()}\tabularnewline +\hline +none available & \Rfunction{rChoiceDialogs::cmdchoose.files(...,dir.only=TRUE)}\tabularnewline +\hline +\end{tabular} +\begin{itemize} +\item For \Rfunction{rchoose.files()}, the dispatch proceeds as follows: +\end{itemize} +\begin{tabular}{|c|c|} +\hline + & \Rfunction{rchoose.files()}\tabularnewline +\hline +\hline +JAVA & \Rfunction{rChoiceDialogs::jchoose.files()}\tabularnewline +\hline +TCL/TK & \Rfunction{rChoiceDialogs::tkchoose.files()}\tabularnewline +\hline +none available & \Rfunction{rChoiceDialogs::cmdchoose.files()}\tabularnewline +\hline +\end{tabular}\\ + + +On Mac OS X, the Java mechanism is bypassed for the reasons discussed +above. One can install an alternative Java SE, but this package does +not attempt to detect the presence of an alternative. + +On Windows one could use the native \Rfunction{choose.files()} coming +with the R installation, but instead this package's \Rfunction{rchoose.files()} +dispatches to \Rfunction{jchoose.files()} for Windows when possible, +for the reasons outlined above. + +Note that, when the tcltk alternatives are needed, then the tcltk +version must be at level 8.5 (see \url{http://cran.r-project.org/bin/macosx/tools/}). + + +\section{Session information } + +This version of rChoiceDialogs has been developed with R 2.11.0 and +has been tested with up to R 2.15.0. + +R session information: +\begin{dummy} +<>= + +library(rChoiceDialogs) + +toLatex(sessionInfo()) + +@ + +\end{dummy} + +\end{document}