Description Usage Arguments Details Examples
View source: R/SimpleDialogMaker.r
An RGtk2/gWidgetsRGtk2 based package for quick and easy dialog development.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | run.dialog(func,
pos = -1,
envir = as.environment(pos),
dlg.list = tryCatch(
get(paste(func.name, "dialog", sep="."),
envir=envir),
error =function(e) NULL),
var.browser=NULL,
parent.window=NULL,
auto.assign=TRUE,
do.long.running=FALSE,
OK_handler= default.handler,
output.name.rule = "append",
output.name = NULL,
do.logging = TRUE,
log.handler = NULL,
user.args = NULL,
...)
|
func |
Function to be run when "OK" is pressed |
pos |
where to look for the dialog markup (see the details section) |
envir |
alternative specification of environment |
dlg.list |
Optional list containing dialog markup |
var.browser |
An optional gWidgets gvarbrowser |
parent.window |
An optional parent window to set modal |
auto.assign |
Assign the function return value, if it exists, to the global environment with an automatically assigned name |
output.name.rule |
Rule for assigning output name |
do.long.running |
Use long running task routine for Windows |
OK_handler |
Function to pass do.call(func, args to) |
output.name |
Name of return value; overrides auto.assign and output.name.rule |
do.logging |
Send the deparsed function call to an external function? |
log.handler |
Function to take the deparsed function call |
user.args |
Optional values to pass to the dialog which overrule those in dialog |
... |
Additional arguments |
This package is intended to assist rapid development of simple dialogs to serve as front-ends to existing R functions. It is a riff off (or rip off) of ideas from John Verzani's traitr toolkit where flexibility is sacrificed for ease of use. Complex layouts are not supported; this package is for getting things working quickly, not necessarily looking beautiful.
To create a working dialog that calls a function, a corresponding markup list is needed specifying how each argument of
the function should look on the screen - in other words, what widgets to use. Then run.dialog()
can be called on the function.
Calling run.dialog()
If your function is called MyFunction
and the markup list is called
MyFunction.dialog
or .MyFunction.dialog
then calling
run.dialog(MyFunction)
will attempt to locate the corresponding markup list and create and show the dialog. When the user presses "OK"
the dialog will call the function with the specified arguments.
The dialog will be modal and centered on the gtkWindow parent.window if this is specified. The R main loop will be blocked until the dialog is destroyed.
Alternatively, run.dialog(MyFunction,
dlg.list=MyMarkupList) will
explicitly specify the dialog markup list for MyFunction
.
Return Values
run.dialog()
returns a list
containing retval
and args
, where retval is the return value
of the function call and args is a list containing the named arguments
specified from the dialog.
Dialog Markup Specification
For a function MyFunction with signature
MyFunction = function(arg1, arg2, ...)
the dialog markup list is specified by
MyFunction.dialog = list(
dialog_markup = value0, ...,
arg1.dialogItem1 = value_of_arg1, markup1 = value1, ...,
arg2.dialogItem2 = value_of_arg2, markup2 = value2, ...,
...
)
The only necessary items in the markup list are those of form
argn.dialogItem = value_of_argn
The name arg1.dialogItem
in the MyFunction.dialog markup list
tells run.dialog()
to display a widget of type dialogItem
corresponding to arg1
. This widget is initialized
to value_of_arg1
and passes this value as the arg1
parameter to MyFunction
when "OK" is clicked.
Optional markup elements that affect the entire dialog
are specified by dialog_markup
items before the first arg.dialogItem
,
and markup elements affecting individual dialogItems are specified between them and the
next dialogItem (or in the case of the last item, the end of the list).
dialogItem can be any one of the following: integerItem, numericItem, rangeItem, stringItem, trueFalseItem, choiceItem, radiobuttonItem, objectItem, dataframeItem, fileItem, variableSelectorItem, listItem, buttonItem. Each of these Items displays a different commonly used dialog GUI widget which are listed below.
Most widgets are also set into a small rectangular frame which contains a label. By default the label is set to the name of the corresponding function argument, but this can be set using the label
markup.
The widgets are laid out very simply within the dialog GUI, set top to bottom in
a column. If the column layout is told to break using the BREAK=TRUE
markup,
another column is added to the left hand side and the widgets after that point are laid out into the new column. An optional label for the entire
dialog can be added to the top over all columns.
Markup
Markups affecting the entire dialog
These are set before the first
arg.dialogItem
label = "This GUI does x"
sets the label centered over all columns.
title = "My Function"
sets the title of the dialog window.
keep.open = TRUE
tells the dialog to stay open after "OK" is pressed.
This can be useful if your function plots something, and the user
is likely to want to try different plot settings.
show.progress = TRUE
tells run.dialog that the function should display
a dialog while it is executing to allow monitoring of progress and cancellation.
This is based on Felix Andrews' interrupt.c from playwith. If this markup is
present then when "OK" is pressed a small modal Progress dialog will appear
with a cancel button. When this button is pressed, an interrupt signal is sent
and the Progress dialog is destroyed and the main dialog is destroyed if
appropriate. This is not guaranteed to stop all running R processes.
Moreover, if your function arguments contain progressbar
or progresslabel
,
then run.dialog
will pass your function a gtkProgressBar and a gtkLabel
respectively, to allow user monitoring of progress via progressbar$setFraction()
or progressbar$setText()
. See ?gtkProgressBar and ?gtkLabel.
Note 1: if your function updates the progress bar or progress label, it should
give these arguments default NULL values and check they are not missing before
using them, otherwise it will break if run without a dialog.
Note 2: if your dialog markup (as opposed to your function) contains progressbar
or progresslabel arguments, then run.dialog will not pass those widgets to
your function automatically.
long.running = TRUE
tells run.dialog that the function will
run for a long time before returning. This is fairly experimental, and doesn't
work anywhere but Windows yet. In Windows, it will do the following things:
1. Save the R session to the current working directory.
2. Create a batch file containing a command to load the R session,
delete the session file, carry out the function call, and a command
to save the session after the function returns.
3. Spawn a separate R process and call exec(R CMD BATCH batch_file)
to
perform the function, and record that process's process ID (PID).
4. Show a modal window over the dialog with an endlessly repeating
progress bar, and a Cancel button. If the Cancel button is pressed, it
will kill the spawned R process using taskkill PID
and close the progress window.
5. Monitor periodically for the saved session file to appear in the
working directory, and then load the session file and close the
progress window.
Dialog markups that work for all items
arg_name.dialogItem = arg_value
sets the dialog item value, OR,
arg_name.dialogItem = substitute(expression)
sets the value of the widget to the evaluated expression.
label = "This widget specifies x"
sets the label for the widget frame.
tooltip = "the tooltip string"
sets a tooltip over the dialog item
BREAK = TRUE
stops adding widgets to the end of the column and
starts a new column.
indent= 10
adds a 10 pixel indentation to the left hand side of
the widget frame which can be useful to show hierarchical organization. signal = c(signal_type, signal_function,
widget1, widget2, ..., user_data=NULL) specifies a widget signal (see below). More than one signal can be
set for each widget.
signal.at.startup = FALSE
will NOT send the "default" signal from
this dialog element when the dialog is initialized.
set.sensitive=FALSE
will gray out the corresponding widget
suppress=TRUE
will prevent the widget's value from being passed to the
function. This is useful for "dummy" widgets that contain lists of values
to choose from.
visible=FALSE
will just not display the widget. Its value will still
be passed to the function and it can be called normally by signaling functions.
Dialog Items
This is a list of the currently available widgets that can be specified
using markup, together with additional markup that can be used to specify
their behavior.
As well as that, there are set.value() and get.value() methods that work on
most widgets, and also signals which they can emit (see Signal Handling).
set.value() takes an optional propagate
argument which is TRUE by
default. If this is set to FALSE, then the widget won't emit its signal.
This list specifies what the set.value and get.value methods return for each
widget and what behavior leads to each widget emitting a signal.
stringItem: An entry box which can take text input.
x.stringItem = "hi there"
Set and Get Calls:
get.value(item) returns the string value.
Signals:
"default" is emitted when Enter is pressed.
numericItem: A stringItem which coerces the value to a number.
x.numericItem = 1.3
Set and Get Calls:
get.value(item) returns the numeric value.
rangeItem: A horizontal slider for returning a numeric value.
x.rangeItem = c(value=1, from=0, to=2, by=0.1)
The value sets the value, min, max and step.
Set and Get Calls:
get.value(item) returns the numeric value.
Signals:
"default" is emitted when the range is altered.
integerItem: a spin button which takes an integer value.
z.integerItem = 1
z.integerItem = c(value=1, from=0, to=10, by=1)
Set and Get Calls:
get.value(item) returns the integer value.
The value can be specified in two ways, first using a single number,
second with a named vector containing the value and the min, max and
step of the spin button.
trueFalseItem: A check box.
an.option.trueFalseItem = TRUE
This widget will not be put in a frame but rather have its label set to
any label markup.
Set and Get Calls:
get.value(item) returns the check box state.
set.value(item, value, propagate=TRUE) sets the item to the logical value.
Signals:
"default" is emitted when the check box is changed.
choiceItem: A combo box allowing selection of a value.
x.choiceItem = c(choice1, value=choice2, choice3, ...)
where "value=" sets the initial choice.
Additional markup:
by.index=T will return the selected indices rather than their strings.
item.labels = c("A", "B", "C") will display the choices as these labels
rather than the values given.
The item.labels vector must be the same length as the values vector if it exists.
Set and Get Calls:
get.value(item) returns the selected choice.
get.value(item, selected=F) returns all of the choices in the choiceItem.
set.value(item, value, propagate=TRUE) sets the available choices in the choiceItem to
the vector (or possibly NULL) value.
Signals:
"default" is emitted when the selection is changed. Note that popping up
the list box will not signal.
radiobuttonItem: Identically specified to choiceItem but shows radio
buttons rather than a combo box. Better for small numbers of choices
or longer choice names. Also, the choices in radiobuttonItem cannot be
changed using set.value(), unlike choiceItem.
Markup for radiobuttonItem is the same as choiceItem.
Set and Get Calls:
get.value(item) returns the selected choice.
set.value(item, value, propagate=TRUE) sets the item to the value and throws an
error if it is not one of the available choices.
Signals:
"default" is emitted when the selection is changed.
fileItem: a label and a button. When the button is pressed a
file name can be selected or typed in.
fileName.fileItem = "C:/R/test.R"
Additional markup:
extension = "xls" opens *.xls
type = "open", "save", "selectdir" gives options to open, save
or select directories
multiple = TRUE allows multiple file selection
(not compatible with type = "selectdir")
Set and Get Calls:
get.value(item) returns a string or vector of strings
corresponding to the selected files or directories.
No set.value() call yet.
Signals:
"default" is emitted when any file is selected.
objectItem: a label and a button. When the button is pressed a
chooser dialog opens allowing selection of objects from the global
environment (using a gWidgets gvarbrowser) on either double
click or select and close.
Its value is a string containing the name of the default object,
otherwise NULL or "".
data.objectItem = "iris"
Additional markup:
data.types ="list" specifies a list of data types. If your selected object
from the chooser doesn't match that type, it won't change the selected
value.
as.character =TRUE means that the name of the selected dataset rather
than the symbol will get passed back to the function.
Set and Get Calls:
get.value(item) returns the selected object name(the string) rather than
the object itself. This is slightly inconsistent with objectItem's
default returned value to the function which is the object symbol.
No set.value() call yet.
Signals:
"default" is emitted when any object is selected.
dataframeItem: identical to objectItem with default data.type markup of
c("data.frame", "matrix"). Also, if a
gWidgetsRGtk2 gvarbrowser is specified
in run.dialog(..., var.browser),
the FIRST dataframeItem
in the dialog will have its value set to any
dataframe or array selected
in the gvarbrowser.
variableSelectorItem: a widget which displays a list with checkboxes to
choose a subset of strings. The check box column header is labeled
"Select All" and clicking it will alternate between selecting and deselecting
all items.
myColumns.variableSelectorItem = letters[1:5]
myColumns.variableSelectorItem = substitute(colnames(iris))
A variableSelectorItem will pass to the function a
(possibly zero-length) vector containing the selected strings.
Set and Get Calls:
get.value(item) returns the selected values.
set.value(item, letters[1:5], propagate=TRUE) sets the values in the item.
Signals:
"default" is emitted when the check boxes are altered anywhere.
listItem: an widget containing a simple list box set in a panel with
buttons labeled with right and left arrows next to it.
The list allows multiple selections.
myColumns.listItem = substitute(colnames(iris))
nothingYet.listItem = NULL
Additional markup:
show.arrows = FALSE turns displaying the arrow buttons off.
max.items = 2 sets the maximum number of items the listItem can
contain to 2.
Set and Get Calls:
get.value(item, select=TRUE) returns the selected values only.
get.value(item, select=FALSE) returns all values.
set.value(item, letters[1:5], propagate=TRUE) sets the values in the list item.
Signals:
"default" is emitted when the list is clicked anywhere.
"add" is emitted when the right-arrow button is clicked.
"subtract" is emitted when the left-arrow button is clicked.
buttonItem: a frameless button.
button.buttonItem = "Click Me"
Set and Get Calls:
None, yet.
Signals:
"clicked" is emitted when the button is clicked.
Dot Arguments
If a markup item called ....stringItem is present, run.dialog() will
display it as a stringItem widget with an "Additional Arguments" label.
When the dialog "OK" is clicked run.dialog() will run
eval(parse(text=get.value(text))) on whatever text is put in that markup,
then place any additional items as additional arguments to the function.
Signaling
Signal handling can be specified to support some commonly required
function dialog behaviors. For example, deselecting a checkbox might set
another widget to insensitive (grayed out), or some items might be moved
between list boxes.
Signaling is specified using the signaling markup, set after a dialog item: signal = c(signal_type, signal_function, widget1_arg, widget2_arg, ..., user_data=NULL) containing the following specifications:
signal_type is a string, for example "default", "clicked", etc.
All the dialogItems will broadcast a signal called "default"
whenever something happens to them corresponding to a user interaction.
This is usually what you're going to want to connect a signal to, but
there are exceptions.
signal_function is a function or a name of a function visible in the environment run.dialog is called from. It has this signature:
signal_function(item, widget1, widget2, ..., user_data=NULL)
item is the widget that sent the signal;
widget1, widget2 are GtkWidget objects specified by ;
user_data is the optionally specified user data
widget1_arg, widget2_arg, ... are the function argument strings
corresponding to the widgets being passed to the signal_function.
user_data is optional additional data to send to the function.
Within your signal_function, you're going to want to be able to get and
set the values your widgets take.
You can do this using the get.value(widget)
and
set.value(widget)
calls. In some cases these calls can take
additional arguments. See the DensityHistogram example below.
Actually, we could use the built-in function toggle.sensitive which does the
same thing (the commented-out #signal line). In this case, passing a string
as the signaling function will make run.dialog search for a function with this
name.
One further question is, how does run.dialog set the rangeItem to be
insensitive the first time it opens? By default, run.dialog()
calls the "default" signal from every one of the widgets when it opens,
unless either
(a) they are set to being insensitive or
(b) the widget signal.on.startup markup is set to FALSE.
Because the default signal from some widgets can set others to being
insensitive, this allows reasonable behavior for hierarchically grouped
toggled sensitive widgets. On the other hand, it may still be desirable to
prevent widgets firing their signals when the dialog is starting,
for example if you have many widgets performing some action like refreshing a
list. In this case, setting signal.on.startup to FALSE for most of them
should fix that problem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | ## Not run:
# A simple histogram plotting example:
SimpleHistogram = function(N) hist(rnorm(N))
SimpleHistogram.dialog = list(label = "A density-plotting histogram dialog",
N.integerItem = 50, label = "Value of N")
run.dialog(SimpleHistogram)
# end example
# example 2
# Function to plot a histogram, optionally adding a density plot with
# adjustable bandwidth. If add.density is false, gray out the bandwidth range.
# This is what's going on in the "signal" markup from the add.density widget:
# We specify the "default" signal from the add.density trueFalseItem
# Then specify the signal function, which takes the add.density
# trueFalseItem as its first argument and the bw.rangeItem
# as its second. In the function, we first of all
# get the value of the trueFalseItem (which is TRUE or FALSE)
# and call gtkWidgetSetSensitive on bw.widget with this value
# (see the RGtk Help for gtkWidget)
# The last element of the signal markup is the string "bw"
# which run.dialog() replaces with the corresponding bw.rangeItem and
# passes to the called signal function as its second argument.
DensityHistogram = function(N, add.density, bw=NULL)
{
x <- rnorm(N)
hist(x, probability=add.density)
if(add.density) points(density(x, bw=bw), type = "l")
}
DensityHistogram.dialog = list(
#keep.open = TRUE, # uncomment to keep the dialog open
label = "A density-plotting histogram dialog",
N.integerItem = c(value=100, from=10, to=1000, by=10), label = "Value of X",
add.density.trueFalseItem = FALSE, label = "Add Density Plot?",
signal = c("default",
function(item, bw.widget) bw.widget$setSensitive(get.value(item)), "bw"),
# signal = c("default", "toggle.sensitive", "bw"), # using the built-in
bw.rangeItem = c(value=0.3, from=0, to=2, by=0.05), label = "Bandwidth")
run.dialog(DensityHistogram)
# end example 2
# Angle display demo, from Graham Williams
demo(MakeAngle)
# Cancel dialog demo
demo(ProgressBar)
## End(Not run)
|
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.