com.codename1.ui.Dialog Maven / Gradle / Ivy
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.codename1.ui;
import com.codename1.io.Log;
import com.codename1.ui.animations.Transition;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.geom.Rectangle;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.FlowLayout;
import com.codename1.ui.layouts.GridLayout;
import com.codename1.ui.layouts.Layout;
import com.codename1.ui.plaf.Border;
import com.codename1.ui.plaf.LookAndFeel;
import com.codename1.ui.plaf.Style;
import com.codename1.ui.plaf.UIManager;
import java.util.Hashtable;
import java.util.Map;
/**
* A dialog is a form that occupies a part of the screen and appears as a modal
* entity to the developer. Dialogs allow us to prompt users for information and
* rely on the information being available on the next line after the show method.
* Modality indicates that a dialog will block the calling thread even if the
* calling thread is the EDT. Notice that a dialog will not release the block
* until dispose is called even if show() from another form is called! Events are still performed thanks
* to the {@link com.codename1.ui.Display#invokeAndBlock(java.lang.Runnable)} capability of the
* Display
class.
* To determine the size of the dialog use the show method that accepts 4 integer
* values, notice that these values accept margin from the four sides rather than x, y, width
* and height values!
* It's important to style a Dialog
using {@link Dialog#getDialogStyle()} or
* {@link Dialog#setDialogUIID(java.lang.String)} methods rather than styling the dialog object directly.
*
* The Dialog
class also includes support for popup dialog which is a dialog type that is positioned
* next to a component or screen area and points an arrow at that location.
*
*
* Typical dialog usage looks like this:
*
*
* See this sample for showing a dialog at the bottom of the screen:
*
*
*
* @author Shai Almog
* @see Display#invokeAndBlock(java.lang.Runnable)
*/
public class Dialog extends Form {
/**
* The default pointer out of bounds dispose behavior, notice that
* this only applies to dialogs and not popup dialogs where this is
* always true by default
* @return the defaultDisposeWhenPointerOutOfBounds
*/
public static boolean isDefaultDisposeWhenPointerOutOfBounds() {
return defaultDisposeWhenPointerOutOfBounds;
}
/**
* The default pointer out of bounds dispose behavior, notice that
* this only applies to dialogs and not popup dialogs where this is
* always true by default
* @param aDefaultDisposeWhenPointerOutOfBounds the defaultDisposeWhenPointerOutOfBounds to set
*/
public static void setDefaultDisposeWhenPointerOutOfBounds(
boolean aDefaultDisposeWhenPointerOutOfBounds) {
defaultDisposeWhenPointerOutOfBounds =
aDefaultDisposeWhenPointerOutOfBounds;
}
/**
* Indicates whether the dialog has been disposed
*/
private boolean disposed;
/**
* Constant indicating the type of alert to indicate the sound to play or
* icon if none are explicitly set
*/
public static final int TYPE_NONE = 0;
/**
* Constant indicating the type of alert to indicate the sound to play or
* icon if none are explicitly set
*/
public static final int TYPE_ALARM = 1;
/**
* Constant indicating the type of alert to indicate the sound to play or
* icon if none are explicitly set
*/
public static final int TYPE_CONFIRMATION = 2;
/**
* Constant indicating the type of alert to indicate the sound to play or
* icon if none are explicitly set
*/
public static final int TYPE_ERROR = 3;
/**
* Constant indicating the type of alert to indicate the sound to play or
* icon if none are explicitly set
*/
public static final int TYPE_INFO = 4;
/**
* Constant indicating the type of alert to indicate the sound to play or
* icon if none are explicitly set
*/
public static final int TYPE_WARNING = 5;
/**
* Indicates the time in which the alert should be disposed
*/
private long time;
/**
* Indicates the last command selected by the user in this form
*/
private Command lastCommandPressed;
/**
* Indicates that this is a menu preventing getCurrent() from ever returning this class
*/
private boolean menu;
private int dialogType;
private int top = -1;
private int bottom;
private int left;
private int right;
private boolean includeTitle;
private String position;
/**
* Indicates whether Codename One should try to automatically adjust a showing dialog size
* when a screen size change event occurs
*/
private static boolean autoAdjustDialogSize = true;
/**
* Default screen orientation position for the upcoming dialog. By default
* the dialog will be shown at hardcoded coordinates, this method allows us
* to pack the dialog appropriately in one of the border layout based locations
* see BorderLayout for futher details.
*/
private static String defaultDialogPosition;
/**
* Default screen orientation position for the upcoming dialog. By default
* the dialog will be shown at hardcoded coordinates, this method allows us
* to pack the dialog appropriately in one of the border layout based locations
* see BorderLayout for futher details.
*/
private String dialogPosition = defaultDialogPosition;
/**
* Allows a developer to indicate his interest that the dialog should no longer
* scroll on its own but rather rely on the scrolling properties of internal
* scrollable containers. This flag only affects the static show methods within
* this class.
*/
private static boolean disableStaticDialogScrolling;
/**
* Determines whether the execution of a command on this dialog implicitly
* disposes the dialog. This defaults to true which is a sensible default for
* simple dialogs.
*/
private boolean autoDispose = true;
private boolean modal = true;
private Command[] buttonCommands;
private boolean disposeOnRotation;
/**
* The default type for dialogs
*/
private static int defaultDialogType = TYPE_INFO;
/**
* Places commands as buttons at the bottom of the standard static dialogs rather than
* as softbuttons. This is especially appropriate for devices such as touch devices and
* devices without the common softbuttons (e.g. blackberries).
* The default value is false
*/
private static boolean commandsAsButtons = true;
/**
* The default pointer out of bounds dispose behavior, notice that
* this only applies to dialogs and not popup dialogs where this is
* always true by default
*/
private static boolean defaultDisposeWhenPointerOutOfBounds = false;
private boolean disposeWhenPointerOutOfBounds = defaultDisposeWhenPointerOutOfBounds;
private boolean pressedOutOfBounds;
/**
* Returns true if the dialog was disposed automatically due to device rotation
*/
private boolean disposedDueToRotation;
private Label dialogTitle;
private Container dialogContentPane;
/**
* Indicates if we want to enforce directional bias for the popup dialog. If null this field is ignored but if
* its set to a value it biases the system towards a fixed direction for the popup dialog.
*/
private Boolean popupDirectionBiasPortrait;
/**
* Dialog background can be blurred using a Gaussian blur effect, this sets the radius of the Gaussian
* blur. -1 is a special case value that indicates that no blurring should take effect and the default tint mode
* only should be used
*/
private static float defaultBlurBackgroundRadius = -1;
/**
* Dialog background can be blurred using a Gaussian blur effect, this sets the radius of the Gaussian
* blur. -1 is a special case value that indicates that no blurring should take effect and the default tint mode
* only should be used
*/
private float blurBackgroundRadius = defaultBlurBackgroundRadius;
private boolean isUIIDByPopupPosition;
/**
* Constructs a Dialog with a title
*
* @param title the title of the dialog
*/
public Dialog(String title) {
this();
setTitle(title);
}
/**
* Constructs a Dialog with a title
*
* @param title the title of the dialog
* @param lm the layout for the dialog
*/
public Dialog(String title, Layout lm) {
this(lm);
setTitle(title);
}
/**
* Disabling ad padding for dialogs
*/
void initAdPadding(Display d) {
}
/**
* Constructs a Dialog
*
*/
public Dialog() {
this("Dialog", "DialogTitle");
}
/**
* Constructs a Dialog with a layout
*
* @param lm the layout manager
*/
public Dialog(Layout lm) {
this("Dialog", "DialogTitle", lm);
}
Dialog(String dialogUIID, String dialogTitleUIID) {
super();
initImpl(dialogUIID, dialogTitleUIID, null);
}
Dialog(String dialogUIID, String dialogTitleUIID, Layout lm) {
super();
initImpl(dialogUIID, dialogTitleUIID, lm);
}
private void initImpl(String dialogUIID, String dialogTitleUIID, Layout lm) {
super.getContentPane().setUIID(dialogUIID);
super.getTitleComponent().setText("");
super.getTitleComponent().setVisible(false);
super.getTitleArea().setVisible(false);
super.getTitleArea().setUIID("Container");
lockStyleImages(getUnselectedStyle());
titleArea.setVisible(false);
if(lm != null) {
dialogContentPane = new Container(lm);
} else {
dialogContentPane = new Container();
}
dialogContentPane.setUIID("DialogContentPane");
dialogTitle = new Label("", dialogTitleUIID);
super.getContentPane().setLayout(new BorderLayout());
super.getContentPane().addComponent(BorderLayout.NORTH, dialogTitle);
super.getContentPane().addComponent(BorderLayout.CENTER, dialogContentPane);
super.getContentPane().setScrollable(false);
super.getContentPane().setAlwaysTensile(false);
super.getStyle().setBgTransparency(0);
super.getStyle().setBgImage(null);
super.getStyle().setBorder(null);
setSmoothScrolling(false);
deregisterAnimated(this);
}
/**
* When the dialog is disposed this form will show. Notice that this can only be set after show was invoked!
* @param previousForm the previous form
*/
public void setPreviousForm(Form previousForm) {
super.setPreviousForm(previousForm);
}
/**
* Overriden to disable the toolbar in dialogs
* {@inheritDoc}
*/
@Override
protected final void initGlobalToolbar() {
}
public Container getContentPane() {
return dialogContentPane;
}
/**
* {@inheritDoc}
*/
public Layout getLayout() {
return dialogContentPane.getLayout();
}
/**
* {@inheritDoc}
*/
public String getTitle() {
return dialogTitle.getText();
}
/**
* {@inheritDoc}
*/
public void addComponent(Component cmp) {
dialogContentPane.addComponent(cmp);
}
/**
* {@inheritDoc}
*/
public void addComponent(Object constraints, Component cmp) {
dialogContentPane.addComponent(constraints, cmp);
}
/**
* {@inheritDoc}
*/
public void addComponent(int index, Object constraints, Component cmp) {
dialogContentPane.addComponent(index, constraints, cmp);
}
/**
* {@inheritDoc}
*/
public void addComponent(int index, Component cmp) {
dialogContentPane.addComponent(index, cmp);
}
/**
* {@inheritDoc}
*/
public void removeAll() {
dialogContentPane.removeAll();
}
/**
* {@inheritDoc}
*/
public void removeComponent(Component cmp) {
dialogContentPane.removeComponent(cmp);
}
/**
* {@inheritDoc}
*/
public Label getTitleComponent() {
return dialogTitle;
}
/**
* {@inheritDoc}
*/
public Style getTitleStyle() {
return dialogTitle.getStyle();
}
/**
* {@inheritDoc}
*/
public void setLayout(Layout layout) {
dialogContentPane.setLayout(layout);
}
void updateIcsIconCommandBehavior() {
// don't set the app icon to the dialog title
}
/**
* {@inheritDoc}
*/
public void setTitle(String title) {
dialogTitle.setText(title);
}
/**
* {@inheritDoc}
*/
public void setTitleComponent(Label title) {
super.getContentPane().removeComponent(dialogTitle);
dialogTitle = title;
super.getContentPane().addComponent(BorderLayout.NORTH, dialogTitle);
}
/**
* Returns the container that actually implements the dialog positioning.
* This container is normally not accessible via the Codename One API.
*
* @return internal dialog container useful for various calculations.
*/
public Container getDialogComponent() {
return super.getContentPane();
}
/**
* {@inheritDoc}
*/
public void setTitleComponent(Label title, Transition t) {
super.getContentPane().replace(dialogTitle, title, t);
dialogTitle = title;
}
/**
* Simple setter to set the Dialog Style
*
* @param style
*/
public void setDialogStyle(Style style){
super.getContentPane().setUnselectedStyle(style);
}
/**
* Simple setter to set the Dialog uiid
*
* @param uiid the id for the dialog
*/
public void setDialogUIID(String uiid){
super.getContentPane().setUIID(uiid);
}
/**
* Returns the uiid of the dialog
*
* @return the uiid of the dialog
*/
public String getDialogUIID(){
return super.getContentPane().getUIID();
}
/**
* Simple getter to get the Dialog Style
*
* @return the style of the dialog
*/
public Style getDialogStyle(){
return super.getContentPane().getUnselectedStyle();
}
/**
* Initialize the default transition for the dialogs overriding the forms
* transition
*
* @param uim the UIManager instance
*/
protected void initLaf(UIManager uim) {
super.initLaf(uim);
setTransitionOutAnimator(uim.getLookAndFeel().getDefaultDialogTransitionOut());
setTransitionInAnimator(uim.getLookAndFeel().getDefaultDialogTransitionIn());
}
/**
* This method shows the form as a modal alert allowing us to produce a behavior
* of an alert/dialog box. This method will block the calling thread even if the
* calling thread is the EDT. Notice that this method will not release the block
* until dispose is called even if show() from another form is called!
* Modal dialogs Allow the forms "content" to "hang in mid air" this is especially useful for
* dialogs where you would want the underlying form to "peek" from behind the
* form.
*
* @param top space in pixels between the top of the screen and the form
* @param bottom space in pixels between the bottom of the screen and the form
* @param left space in pixels between the left of the screen and the form
* @param right space in pixels between the right of the screen and the form
* @param includeTitle whether the title should hang in the top of the screen or
* be glued onto the content pane
* @return the last command pressed by the user if such a command exists
* @deprecated use the version that doesn't accept the include title, the includeTitle
* feature is no longer supported
*/
public Command show(int top, int bottom, int left, int right, boolean includeTitle) {
return show(top, bottom, left, right, includeTitle, true);
}
/**
*
This method shows the form as a modal alert allowing us to produce a behavior
* of an alert/dialog box. This method will block the calling thread even if the
* calling thread is the EDT. Notice that this method will not release the block
* until dispose is called even if show() from another form is called!
* Modal dialogs Allow the forms "content" to "hang in mid air" this is especially useful for
* dialogs where you would want the underlying form to "peek" from behind the
* form.
* See this sample for showing a dialog at the bottom of the screen:
*
*
* @param top space in pixels between the top of the screen and the form
* @param bottom space in pixels between the bottom of the screen and the form
* @param left space in pixels between the left of the screen and the form
* @param right space in pixels between the right of the screen and the form
* @return the last command pressed by the user if such a command exists
*/
public Command show(int top, int bottom, int left, int right) {
return show(top, bottom, left, right, false, true);
}
/**
* This method shows the form as a modal alert allowing us to produce a behavior
* of an alert/dialog box. This method will block the calling thread even if the
* calling thread is the EDT. Notice that this method will not release the block
* until dispose is called even if show() from another form is called!
* Modal dialogs Allow the forms "content" to "hang in mid air" this is especially useful for
* dialogs where you would want the underlying form to "peek" from behind the
* form.
*
* @param top space in pixels between the top of the screen and the form
* @param bottom space in pixels between the bottom of the screen and the form
* @param left space in pixels between the left of the screen and the form
* @param right space in pixels between the right of the screen and the form
* @param includeTitle whether the title should hang in the top of the screen or
* be glued onto the content pane
* @param modal indicates the dialog should be modal set to false for modeless dialog
* which is useful for some use cases
* @return the last command pressed by the user if such a command exists
* @deprecated use showAtPosition, the includeTitle flag is no longer supported
*/
public Command show(int top, int bottom, int left, int right, boolean includeTitle, boolean modal) {
this.top = top;
this.bottom = bottom;
if(isRTL()){
this.left = right;
this.right = left;
}else{
this.left = left;
this.right = right;
}
//this.includeTitle = includeTitle;
setDisposed(false);
this.modal = modal;
lastCommandPressed = null;
showModal(this.top, this.bottom, this.left, this.right, includeTitle, modal, false);
return lastCommandPressed;
}
/**
* This method shows the form as a modal alert allowing us to produce a behavior
* of an alert/dialog box. This method will block the calling thread even if the
* calling thread is the EDT. Notice that this method will not release the block
* until dispose is called even if show() from another form is called!
*
Modal dialogs Allow the forms "content" to "hang in mid air" this is especially useful for
* dialogs where you would want the underlying form to "peek" from behind the
* form.
*
* @param top space in pixels between the top of the screen and the form
* @param bottom space in pixels between the bottom of the screen and the form
* @param left space in pixels between the left of the screen and the form
* @param right space in pixels between the right of the screen and the form
* @param modal indicates the dialog should be modal set to false for modeless dialog
* which is useful for some use cases
* @return the last command pressed by the user if such a command exists
*/
public Command showAtPosition(int top, int bottom, int left, int right, boolean modal) {
this.top = top;
this.bottom = bottom;
if(isRTL()){
this.left = right;
this.right = left;
}else{
this.left = left;
this.right = right;
}
//this.includeTitle = includeTitle;
setDisposed(false);
this.modal = modal;
lastCommandPressed = null;
showModal(this.top, this.bottom, this.left, this.right, false, modal, false);
return lastCommandPressed;
}
/**
* Disable title bar status for iOS 7 which breaks dialogs
*/
void initTitleBarStatus() {
}
/**
* Indicates the time (in milliseconds) afterwhich the dialog will be disposed
* implicitly
*
* @param time a milliseconds time used to dispose the dialog
*/
public void setTimeout(long time) {
this.time = System.currentTimeMillis() + time;
super.registerAnimatedInternal(this);
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param okText the text to appear in the command dismissing the dialog
* @param cancelText optionally null for a text to appear in the cancel command
* for canceling the dialog
* @return true if the ok command was pressed or if cancelText is null. False otherwise.
*/
public static boolean show(String title, String text, int type, Image icon, String okText, String cancelText) {
return show(title, text, type, icon, okText, cancelText, 0);
}
/**
* {@inheritDoc}
*/
void sizeChangedInternal(int w, int h) {
if(disposeOnRotation) {
disposedDueToRotation = true;
dispose();
Form frm = getPreviousForm();
if(frm != null){
frm.sizeChangedInternal(w, h);
}
return;
}
autoAdjust(w, h);
super.sizeChangedInternal(w, h);
Form frm = getPreviousForm();
if(frm != null){
frm.sizeChangedInternal(w, h);
}
}
/**
* Auto adjust size of the dialog.
* This method is triggered from a sizeChanged event.
*
* @param w width of the screen
* @param h height of the screen
*/
protected void autoAdjust(int w, int h) {
if (autoAdjustDialogSize) {
growOrShrinkImpl(w, h);
}
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param okText the text to appear in the command dismissing the dialog
* @param cancelText optionally null for a text to appear in the cancel command
* for canceling the dialog
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @return true if the ok command was pressed or if cancelText is null. False otherwise.
*/
public static boolean show(String title, String text, int type, Image icon, String okText, String cancelText, long timeout) {
Command[] cmds;
Command okCommand = new Command(okText);
if (cancelText != null) {
cmds = new Command[]{new Command(cancelText), okCommand};
} else {
cmds = new Command[]{okCommand};
}
return show(title, text, okCommand, cmds, type, icon, timeout) == okCommand;
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @return the command pressed by the user
*/
public static Command show(String title, String text, Command[] cmds, int type, Image icon, long timeout) {
return show(title, text, null, cmds, type, icon, timeout);
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param defaultCommand command to be assigned as the default command or null
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @return the command pressed by the user
*/
public static Command show(String title, String text, Command defaultCommand, Command[] cmds, int type, Image icon, long timeout) {
return show(title, text, defaultCommand, cmds, type, icon, timeout, null);
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @param transition the transition installed when the dialog enters/leaves
* @return the command pressed by the user
*/
public static Command show(String title, String text, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
return show(title, text, null, cmds, type, icon, timeout, transition);
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param defaultCommand command to be assigned as the default command or null
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @param transition the transition installed when the dialog enters/leaves
* @return the command pressed by the user
*/
public static Command show(String title, String text, Command defaultCommand, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
Map h = UIManager.getInstance().getBundle();
if(h != null && text != null) {
Object o = h.get(text);
if(o != null) {
text = (String)o;
}
}
TextArea t = new TextArea(text, 3, 30);
t.setUIID("DialogBody");
t.setEditable(false);
return show(title, t, defaultCommand, cmds, type, icon, timeout, transition);
}
/**
* Shows a modal prompt dialog with the given title and text.
*
* @param title The title for the dialog optionally null;
* @param text the text displayed in the dialog
* @param okText the text to appear in the command dismissing the dialog
* @param cancelText optionally null for a text to appear in the cancel command
* for canceling the dialog
* @return true if the ok command was pressed or if cancelText is null. False otherwise.
*/
public static boolean show(String title, String text, String okText, String cancelText) {
return show(title, text, defaultDialogType, null, okText, cancelText);
}
/**
* Shows a modal dialog with the given component as its "body" placed in the
* center.
*
* @param title title for the dialog
* @param body component placed in the center of the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @return the command pressed by the user
*/
public static Command show(String title, Component body, Command... cmds) {
return show(title, body, cmds, defaultDialogType, null);
}
/**
* Shows a modal dialog with the given component as its "body" placed in the
* center.
*
* @param title title for the dialog
* @param body text placed in the center of the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @return the command pressed by the user
*/
public static Command show(String title, String body, Command... cmds) {
TextArea t = new TextArea(body, 3, 30);
t.setUIID("DialogBody");
t.setEditable(false);
return show(title, t, cmds);
}
/**
* Shows a modal dialog with the given component as its "body" placed in the
* center.
*
* @param title title for the dialog
* @param body component placed in the center of the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @return the command pressed by the user
*/
public static Command show(String title, Component body, Command[] cmds, int type, Image icon) {
return show(title, body, cmds, type, icon, 0);
}
/**
* Shows a modal dialog with the given component as its "body" placed in the
* center.
*
* @param title title for the dialog
* @param body component placed in the center of the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @return the command pressed by the user
*/
public static Command show(String title, Component body, Command[] cmds, final int type, Image icon, long timeout) {
return show(title, body, cmds, type, icon, timeout, null);
}
/**
* Shows a modal dialog with the given component as its "body" placed in the
* center.
*
* @param title title for the dialog
* @param body component placed in the center of the dialog
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 infinite time is used
* @param transition the transition installed when the dialog enters/leaves
* @return the command pressed by the user
*/
public static Command show(String title, Component body, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
return show(title, body, null, cmds, type, icon, timeout, transition);
}
private void addButtonBar(Container c) {
super.getContentPane().addComponent(BorderLayout.SOUTH, c);
}
/**
* Places the given commands in the dialog command area, this is very useful for touch devices.
*
* @param cmds the commands to place
* @deprecated this method shouldn't be invoked externally, it should have been private
*/
public void placeButtonCommands(Command[] cmds) {
buttonCommands = cmds;
Container buttonArea;
if(getUIManager().isThemeConstant("dlgCommandGridBool", false)) {
buttonArea = new Container(new GridLayout(1, cmds.length));
} else {
buttonArea = new Container(new FlowLayout(CENTER));
}
buttonArea.setUIID("DialogCommandArea");
String uiid = getUIManager().getThemeConstant("dlgButtonCommandUIID", null);
addButtonBar(buttonArea);
if(cmds.length > 0) {
String lineColor = getUIManager().getThemeConstant("dlgInvisibleButtons", null);
if(cmds.length > 3) {
lineColor = null;
}
int largest = Integer.parseInt(getUIManager().getThemeConstant("dlgCommandButtonSizeInt", "0"));
for(int iter = 0 ; iter < cmds.length ; iter++) {
Button b = new Button(cmds[iter]);
if(uiid != null) {
b.setUIID(uiid);
}
// special case for dialog butons uppercase on Android
if(Button.isCapsTextDefault()) {
b.setCapsText(true);
}
largest = Math.max(b.getPreferredW(), largest);
if(lineColor != null && lineColor.length() > 0) {
int color = Integer.parseInt(lineColor, 16);
Border brd = null;
if(iter < cmds.length - 1) {
brd = Border.createCompoundBorder(Border.createLineBorder(1, color), null, null, Border.createLineBorder(1, color));
} else {
brd = Border.createCompoundBorder(Border.createLineBorder(1, color), null, null, null);
}
b.getUnselectedStyle().setBorder(brd);
b.getSelectedStyle().setBorder(brd);
b.getPressedStyle().setBorder(brd);
}
buttonArea.addComponent(b);
}
for(int iter = 0 ; iter < cmds.length ; iter++) {
buttonArea.getComponentAt(iter).setPreferredW(largest);
}
buttonArea.getComponentAt(0).requestFocus();
}
}
/**
* {@inheritDoc}
*/
public void keyReleased(int keyCode) {
if(commandsAsButtons) {
if(MenuBar.isLSK(keyCode)) {
if(buttonCommands != null && buttonCommands.length > 0) {
dispatchCommand(buttonCommands[0], new ActionEvent(buttonCommands[0],ActionEvent.Type.KeyRelease));
return;
}
}
if(MenuBar.isRSK(keyCode)) {
if(buttonCommands != null && buttonCommands.length > 1) {
dispatchCommand(buttonCommands[1], new ActionEvent(buttonCommands[1],ActionEvent.Type.KeyRelease));
return;
}
}
}
super.keyReleased(keyCode);
}
/**
* Shows a modal dialog with the given component as its "body" placed in the
* center.
*
* @param title title for the dialog
* @param body component placed in the center of the dialog
* @param defaultCommand command to be assigned as the default command or null
* @param cmds commands that are added to the form any click on any command
* will dispose the form
* @param type the type of the alert one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
* @param icon the icon for the dialog, can be null
* @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
* @param transition the transition installed when the dialog enters/leaves
* @return the command pressed by the user
*/
public static Command show(String title, Component body, Command defaultCommand, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
Dialog dialog = new Dialog(title);
dialog.dialogType = type;
dialog.setTransitionInAnimator(transition);
dialog.setTransitionOutAnimator(transition);
dialog.lastCommandPressed = null;
dialog.setLayout(new BorderLayout());
if(cmds != null) {
if(commandsAsButtons) {
dialog.placeButtonCommands(cmds);
} else {
for(int iter = 0 ; iter < cmds.length ; iter++) {
dialog.addCommand(cmds[iter]);
}
}
// maps the first command to back
if(cmds.length == 1 || cmds.length == 2) {
dialog.setBackCommand(cmds[0]);
}
}
if(defaultCommand != null) {
dialog.setDefaultCommand(defaultCommand);
}
dialog.addComponent(BorderLayout.CENTER, body);
if (icon != null) {
dialog.addComponent(BorderLayout.EAST, new Label(icon));
}
if (timeout != 0) {
dialog.setTimeout(timeout);
}
if(body.isScrollable() || disableStaticDialogScrolling){
dialog.setScrollable(false);
}
dialog.show();
return dialog.lastCommandPressed;
}
/**
* {@inheritDoc}
*/
protected void onShow() {
if (dialogType > 0) {
Display.getInstance().playDialogSound(dialogType);
}
}
void onShowCompletedImpl() {
pressedOutOfBounds = false;
disposedDueToRotation = false;
setLightweightMode(false);
onShowCompleted();
if(isDisposed()) {
disposeImpl();
}
if (showListener != null) {
showListener.fireActionEvent(new ActionEvent(this,ActionEvent.Type.Show));
}
}
/**
* {@inheritDoc}
*/
public void showBack() {
showImpl(true);
}
/**
* {@inheritDoc}
*/
public void setScrollable(boolean scrollable) {
getContentPane().setScrollable(scrollable);
}
/**
* The default version of show modal shows the dialog occupying the center portion
* of the screen.
*/
public void show() {
showImpl(false);
}
/**
* The default version of show modal shows the dialog occupying the center portion
* of the screen.
*/
private void showImpl(boolean reverse) {
if(modal && Display.isInitialized() && Display.getInstance().isMinimized()){
Log.p("Modal dialogs cannot be displayed on a minimized app");
return;
}
// this behavior allows a use case where dialogs of various sizes are layered
// one on top of the other
setDisposed(false);
if(top > -1) {
show(top, bottom, left, right, includeTitle, modal);
} else {
if(modal) {
if(getDialogPosition() == null) {
super.showModal(reverse);
} else {
showPacked(getDialogPosition(), true);
}
} else {
showModeless();
}
}
}
/**
* Shows a modeless dialog which is useful for some simpler use cases such as
* progress indication etc...
*/
public void showModeless() {
// this behavior allows a use case where dialogs of various sizes are layered
// one on top of the other
modal = false;
setDisposed(false);
if(top > -1) {
show(top, bottom, left, right, includeTitle, false);
} else {
if(getDialogPosition() == null) {
showDialog(false, false);
} else {
showPacked(getDialogPosition(), false);
}
}
}
void showModal(int top, int bottom, int left, int right, boolean includeTitle, boolean modal, boolean reverse) {
if(Display.isInitialized() && Display.getInstance().isMinimized()){
Log.p("Modal dialogs cannot be displayed on a minimized app");
return;
}
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
// hide the title if no text is there to allow the styles of the dialog title to disappear
if(dialogTitle != null && getUIManager().isThemeConstant("hideEmptyTitleBool", false)) {
boolean b = dialogTitle.getText().length() > 0;
getTitleArea().setVisible(b);
getTitleComponent().setVisible(b);
}
super.showModal(top, bottom, left, right, includeTitle, modal, reverse);
}
/**
* A popup dialog is shown with the context of a component and its selection, it is disposed seamlessly if the back button is pressed
* or if the user touches outside its bounds. It can optionally provide an arrow in the theme to point at the context component. The popup
* dialog has the PopupDialog style by default.
*
* @param c the context component which is used to position the dialog and can also be pointed at
* @return the command that might have been triggered by the user within the dialog if commands are placed in the dialog
*/
public Command showPopupDialog(Component c) {
Rectangle componentPos = c.getSelectedRect();
componentPos.setX(componentPos.getX() - c.getScrollX());
componentPos.setY(componentPos.getY() - c.getScrollY());
return showPopupDialog(componentPos);
}
/**
* A popup dialog is shown with the context of a component and its selection, it is disposed seamlessly if the back button is pressed
* or if the user touches outside its bounds. It can optionally provide an arrow in the theme to point at the context component. The popup
* dialog has the PopupDialog style by default.
*
* @param rect the screen rectangle to which the popup should point
* @return the command that might have been triggered by the user within the dialog if commands are placed in the dialog
*/
public Command showPopupDialog(Rectangle rect) {
if(getDialogUIID().equals("Dialog")) {
setDialogUIID("PopupDialog");
if(getTitleComponent().getUIID().equals("DialogTitle")) {
getTitleComponent().setUIID("PopupDialogTitle");
}
getContentPane().setUIID("PopupContentPane");
}
disposeOnRotation = true;
disposeWhenPointerOutOfBounds = true;
Command backCommand = null;
if(getBackCommand() == null) {
backCommand = new Command("Back");
setBackCommand(backCommand);
}
Component contentPane = super.getContentPane();
Label title = super.getTitleComponent();
int menuHeight = calcMenuHeight();
UIManager manager = getUIManager();
// hide the title if no text is there to allow the styles of the dialog title to disappear, we need this code here since otherwise the
// preferred size logic of the dialog won't work with large title borders
if(dialogTitle != null && manager.isThemeConstant("hideEmptyTitleBool", false)) {
boolean b = getTitle().length() > 0;
getTitleArea().setVisible(b);
getTitleComponent().setVisible(b);
if(!b && manager.isThemeConstant("shrinkPopupTitleBool", true)) {
getTitleComponent().setPreferredSize(new Dimension(0,0));
getTitleComponent().getStyle().setBorder(null);
getTitleArea().setPreferredSize(new Dimension(0,0));
if(getContentPane().getClientProperty("$ENLARGED_POP") == null) {
getContentPane().putClientProperty("$ENLARGED_POP", Boolean.TRUE);
int cpPaddingTop = getContentPane().getStyle().getPaddingTop();
int titlePT = getTitleComponent().getStyle().getPaddingTop();
byte[] pu = getContentPane().getStyle().getPaddingUnit();
if(pu == null){
pu = new byte[4];
}
pu[0] = Style.UNIT_TYPE_PIXELS;
getContentPane().getStyle().setPaddingUnit(pu);
int pop = Display.getInstance().convertToPixels(manager.getThemeConstant("popupNoTitleAddPaddingInt", 1), false);
getContentPane().getStyle().setPadding(TOP, pop + cpPaddingTop + titlePT);
}
}
}
// allows a text area to recalculate its preferred size if embedded within a dialog
revalidate();
Style contentPaneStyle = getDialogStyle();
boolean restoreArrow = false;
if(manager.isThemeConstant(getDialogUIID()+ "ArrowBool", false)) {
Image t = manager.getThemeImageConstant(getDialogUIID() + "ArrowTopImage");
Image b = manager.getThemeImageConstant(getDialogUIID() + "ArrowBottomImage");
Image l = manager.getThemeImageConstant(getDialogUIID() + "ArrowLeftImage");
Image r = manager.getThemeImageConstant(getDialogUIID() + "ArrowRightImage");
Border border = contentPaneStyle.getBorder();
if(border != null) {
border.setImageBorderSpecialTile(t, b, l, r, rect);
restoreArrow = true;
}
} else {
Border border = contentPaneStyle.getBorder();
if(border != null) {
border.setTrackComponent(rect);
}
}
int prefHeight = contentPane.getPreferredH();
int prefWidth = contentPane.getPreferredW();
if(contentPaneStyle.getBorder() != null) {
prefWidth = Math.max(contentPaneStyle.getBorder().getMinimumWidth(), prefWidth);
prefHeight = Math.max(contentPaneStyle.getBorder().getMinimumHeight(), prefHeight);
}
prefWidth += getUIManager().getLookAndFeel().getVerticalScrollWidth();
int availableHeight = Display.getInstance().getDisplayHeight() - menuHeight - title.getPreferredH();
int availableWidth = Display.getInstance().getDisplayWidth();
int width = Math.min(availableWidth, prefWidth);
int x = 0;
int y = 0;
Command result;
boolean showPortrait;
if(popupDirectionBiasPortrait != null) {
showPortrait = popupDirectionBiasPortrait.booleanValue();
} else {
showPortrait = Display.getInstance().isPortrait();
}
// if we don't have enough space then disregard device orientation
if(showPortrait) {
if(availableHeight < (availableWidth - rect.getWidth()) / 2) {
showPortrait = false;
}
} else {
if(availableHeight / 2 > availableWidth - rect.getWidth()) {
showPortrait = true;
}
}
if(showPortrait) {
if(width < availableWidth) {
int idealX = rect.getX() - width / 2 + rect.getSize().getWidth() / 2;
// if the ideal position is less than 0 just use 0
if(idealX > 0) {
// if the idealX is too far to the right just align to the right
if(idealX + width > availableWidth) {
x = availableWidth - width;
} else {
x = idealX;
}
}
}
if(rect.getY() < availableHeight / 2) {
// popup downwards
if (getDialogUIID().equals("PopupDialog") && isUIIDByPopupPosition) {
getContentPane().setUIID("PopupContentPaneDownwards");
}
y = rect.getY() + rect.getSize().getHeight();
int height = Math.min(prefHeight, availableHeight - y);
result = show(y, availableHeight - height - y, x, availableWidth - width - x, true, true);
} else {
// popup upwards
if (getDialogUIID().equals("PopupDialog") && isUIIDByPopupPosition) {
getContentPane().setUIID("PopupContentPaneUpwards");
}
int height = Math.min(prefHeight, availableHeight - (availableHeight - rect.getY()));
y = rect.getY() - height;
result = show(y, availableHeight - height - y, x, availableWidth - width - x, true, true);
}
} else {
int height = Math.min(prefHeight, availableHeight);
if(height < availableHeight) {
int idealY = rect.getY() - height / 2 + rect.getSize().getHeight() / 2;
// if the ideal position is less than 0 just use 0
if(idealY > 0) {
// if the idealY is too far up just align to the top
if(idealY + height > availableHeight) {
y = availableHeight - height;
} else {
y = idealY;
}
}
}
if(prefWidth > rect.getX()) {
// popup right
if (getDialogUIID().equals("PopupDialog") && isUIIDByPopupPosition) {
getContentPane().setUIID("PopupContentPaneRight");
}
x = rect.getX() + rect.getSize().getWidth();
if(x + prefWidth > availableWidth){
x = availableWidth - prefWidth;
}
width = Math.min(prefWidth, availableWidth - x);
result = show(y, availableHeight - height - y, Math.max(0, x), Math.max(0, availableWidth - width - x), true, true);
} else {
// popup left
if (getDialogUIID().equals("PopupDialog") && isUIIDByPopupPosition) {
getContentPane().setUIID("PopupContentPaneLeft");
}
width = Math.min(prefWidth, availableWidth - (availableWidth - rect.getX()));
x = rect.getX() - width;
result = show(y, availableHeight - height - y, Math.max(0, x), Math.max(0, availableWidth - width - x), true, true);
}
}
if(restoreArrow) {
contentPaneStyle.getBorder().clearImageBorderSpecialTile();
}
if(result == backCommand) {
return null;
}
return result;
}
private int calcMenuHeight() {
if(getSoftButtonCount() > 1) {
Component menuBar = getSoftButton(0).getParent();
Style menuStyle = menuBar.getStyle();
return menuBar.getPreferredH() + menuStyle.getVerticalMargins();
}
return 0;
}
/**
* Convenience method to show a dialog sized to match its content.
*
* @param position one of the values from the BorderLayout class e.g. BorderLayout.CENTER, BorderLayout.NORTH etc.
* @param modal whether the dialog should be modal or modaless
* @return the command selected if the dialog is modal and disposed via a command
*/
public Command showPacked(String position, boolean modal) {
return showPackedImpl(position, modal, false);
}
/**
* Convenience method to show a dialog stretched to one of the sides
*
* @param position one of the values from the BorderLayout class except for center e.g. BorderLayout.NORTH, BorderLayout.EAST etc.
* @param modal whether the dialog should be modal or modaless
* @return the command selected if the dialog is modal and disposed via a command
*/
public Command showStretched(String position, boolean modal) {
return showPackedImpl(position, modal, true);
}
/**
* Convenience method to show a dialog stretched to one of the sides
*
* @param position one of the values from the BorderLayout class except for center e.g. BorderLayout.NORTH, BorderLayout.EAST etc.
* @param modal whether the dialog should be modal or modaless
* @return the command selected if the dialog is modal and disposed via a command
* @deprecated due to typo use showStretched instead
*/
public Command showStetched(String position, boolean modal) {
return showPackedImpl(position, modal, true);
}
/**
* Returns the preferred size of the dialog, this allows developers to position a dialog
* manually in arbitrary positions.
*
* @return the preferred size of this dialog
*/
public Dimension getDialogPreferredSize() {
Component contentPane = super.getContentPane();
Style contentPaneStyle = getDialogStyle();
int width = Display.getInstance().getDisplayWidth();
int prefHeight = contentPane.getPreferredH();
int prefWidth = contentPane.getPreferredW();
prefWidth = Math.min(prefWidth, width);
if(contentPaneStyle.getBorder() != null) {
prefWidth = Math.max(contentPaneStyle.getBorder().getMinimumWidth(), prefWidth);
prefHeight = Math.max(contentPaneStyle.getBorder().getMinimumHeight(), prefHeight);
}
return new Dimension(prefWidth, prefHeight);
}
/**
* Convenience method to show a dialog sized to match its content.
*
* @param position one of the values from the BorderLayout class e.g. BorderLayout.CENTER, BorderLayout.NORTH etc.
* @param modal whether the dialog should be modal or modaless
* @return the command selected if the dialog is modal and disposed via a command
*/
private Command showPackedImpl(String position, boolean modal, boolean stretch) {
if(getTitle() == null) {
setTitle("");
}
this.position = position;
int height = Display.getInstance().getDisplayHeight();
int width = Display.getInstance().getDisplayWidth();
if(top > -1){
refreshTheme();
}
Component contentPane = super.getContentPane();
if(dialogTitle != null && getUIManager().isThemeConstant("hideEmptyTitleBool", false)) {
boolean b = getTitle().length() > 0;
getTitleArea().setVisible(b);
getTitleComponent().setVisible(b);
}
Style contentPaneStyle = contentPane.getStyle();
revalidate();
int prefHeight = contentPane.getPreferredH();
int prefWidth = contentPane.getPreferredW();
prefWidth = Math.min(prefWidth, width);
if(contentPaneStyle.getBorder() != null) {
prefWidth = Math.max(contentPaneStyle.getBorder().getMinimumWidth(), prefWidth);
prefHeight = Math.max(contentPaneStyle.getBorder().getMinimumHeight(), prefHeight);
}
int topBottom = Math.max(0, (height - prefHeight) / 2);
int leftRight = Math.max(0, (width - prefWidth) / 2);
if(position.equals(BorderLayout.CENTER)) {
show(topBottom, topBottom, leftRight, leftRight, true, modal);
return lastCommandPressed;
}
if(position.equals(BorderLayout.EAST)) {
if(stretch) {
show(0, 0, Math.max(0, width - prefWidth), 0, true, modal);
} else {
show(topBottom, topBottom, Math.max(0, width - prefWidth), 0, true, modal);
}
return lastCommandPressed;
}
if(position.equals(BorderLayout.WEST)) {
if(stretch) {
show(0, 0, 0, Math.max(0, width - prefWidth), true, modal);
} else {
show(topBottom, topBottom, 0, Math.max(0, width - prefWidth), true, modal);
}
return lastCommandPressed;
}
if(position.equals(BorderLayout.NORTH)) {
if(stretch) {
show(0, Math.max(0, height - prefHeight), 0, 0, true, modal);
} else {
show(0, Math.max(0, height - prefHeight), leftRight, leftRight, true, modal);
}
return lastCommandPressed;
}
if(position.equals(BorderLayout.SOUTH)) {
if(stretch) {
show(Math.max(0, height - prefHeight), 0, 0, 0, true, modal);
} else {
show(Math.max(0, height - prefHeight), 0, leftRight, leftRight, true, modal);
}
return lastCommandPressed;
}
throw new IllegalArgumentException("Unknown position: " + position);
}
/**
* Closes the current form and returns to the previous form, releasing the
* EDT in the process
*/
public void dispose() {
if(isDisposed()){
return;
}
setDisposed(true);
// the dispose parent method might send us back to the form while the command
// within the dialog might be directing us to another form causing a "blip"
if(!menu) {
super.dispose();
}
}
/**
* Shows a modal dialog and returns the command pressed within the modal dialog
*
* @return last command pressed in the modal dialog
*/
public Command showDialog() {
lastCommandPressed = null;
show();
return lastCommandPressed;
}
/**
* Invoked to allow subclasses of form to handle a command from one point
* rather than implementing many command instances
*
* @param cmd the action command
*/
protected void actionCommand(Command cmd) {
// this is important... In a case of nested dialogs based on commands/events a command might be
// blocked by a different dialog, so when that dialog is disposed (as a result of a command) going
// back to this dialog will block that command from proceeding and it can be fired again later
// E.g.:
// Dialog A has a command which triggers dialog B on top.
// User presses Cancel in dialog B
// Dialog A is shown as a result of dialog B dispose method
// Cancel command event firing is blocked since the dialog B dispose method is now blocking on dialog A show()...
// When dialog A is disposed using the OK command the OK command is sent correctly and causes dispose
// EDT is released which also releases the Cancel for dialog B to keep processing...
// Cancel for dialog B proceeds in the event chain reaching this method....
// lastCommandPressed can be overrwritten if this check isn't made!!!
if(!autoDispose || lastCommandPressed == null) {
lastCommandPressed = cmd;
}
if(menu || (autoDispose && cmd.isDisposesDialog())) {
dispose();
}
}
/**
* {@inheritDoc}
*/
public boolean animate() {
isTimedOut();
return false;
}
private boolean isTimedOut(){
if (time != 0 && System.currentTimeMillis() >= time) {
time = 0;
dispose();
deregisterAnimatedInternal(this);
return true;
}
return false;
}
/**
* Indicates that this is a menu preventing getCurrent() from ever returning this class
*/
boolean isMenu() {
return menu;
}
/**
* Indicates that this is a menu preventing getCurrent() from ever returning this class
*/
void setMenu(boolean menu) {
this.menu = menu;
}
/**
* Prevent a menu from adding the select button
*/
void addSelectCommand() {
if (!menu) {
getMenuBar().addSelectCommand(getSelectCommandText());
}
}
/**
* Allows us to indicate disposed state for dialogs
*/
boolean isDisposed() {
return disposed || isTimedOut();
}
/**
* Allows us to indicate disposed state for dialogs
*/
void setDisposed(boolean disposed) {
this.disposed = disposed;
}
/**
* Determines whether the execution of a command on this dialog implicitly
* disposes the dialog. This defaults to true which is a sensible default for
* simple dialogs.
*
* @return true if this dialog disposes on any command
*/
public boolean isAutoDispose() {
return autoDispose;
}
/**
* Determines whether the execution of a command on this dialog implicitly
* disposes the dialog. This defaults to true which is a sensible default for
* simple dialogs.
*
* @param autoDispose true if this dialog disposes on any command
*/
public void setAutoDispose(boolean autoDispose) {
this.autoDispose = autoDispose;
}
/**
* Default screen orientation position for the upcoming dialog. By default
* the dialog will be shown at hardcoded coordinates, this method allows us
* to pack the dialog appropriately in one of the border layout based locations
* see BorderLayout for futher details.
*
* @param p for dialogs on the sceen using BorderLayout orientation tags
*/
public static void setDefaultDialogPosition(String p) {
defaultDialogPosition = p;
}
/**
* Default screen orientation position for the upcoming dialog. By default
* the dialog will be shown at hardcoded coordinates, this method allows us
* to pack the dialog appropriately in one of the border layout based locations
* see BorderLayout for futher details.
*
* @return position for dialogs on the sceen using BorderLayout orientation tags
*/
public static String getDefaultDialogPosition() {
return defaultDialogPosition;
}
/**
* The type of the dialog can be one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
*
* @return can be one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
*/
public int getDialogType() {
return dialogType;
}
/**
* The type of the dialog can be one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
*
* @param dialogType can be one of TYPE_WARNING, TYPE_INFO,
* TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
*/
public void setDialogType(int dialogType) {
this.dialogType = dialogType;
}
/**
* The default type for dialogs
*
* @param d the default type for the dialog
*/
public static void setDefaultDialogType(int d) {
defaultDialogType = d;
}
/**
* The default type for dialogs
*
* @return the default type for the dialog
*/
public static int getDefaultDialogType() {
return defaultDialogType;
}
/**
* Indicates whether Codename One should try to automatically adjust a showing dialog size
* when a screen size change event occurs
*
* @param a true to indicate that Codename One should make a "best effort" to resize the dialog
*/
public static void setAutoAdjustDialogSize(boolean a) {
autoAdjustDialogSize = a;
}
/**
* Indicates whether Codename One should try to automatically adjust a showing dialog size
* when a screen size change event occurs
*
* @return true to indicate that Codename One should make a "best effort" to resize the dialog
*/
public static boolean isAutoAdjustDialogSize() {
return autoAdjustDialogSize;
}
/**
* Allows a developer to indicate his interest that the dialog should no longer
* scroll on its own but rather rely on the scrolling properties of internal
* scrollable containers. This flag only affects the static show methods within
* this class.
*
* @param d indicates whether scrolling should be active or not
*/
public static void setDisableStaticDialogScrolling(boolean d) {
disableStaticDialogScrolling = d;
}
/**
* Allows a developer to indicate his interest that the dialog should no longer
* scroll on its own but rather rely on the scrolling properties of internal
* scrollable containers. This flag only affects the static show methods within
* this class.
*
* @return true if scrolling should be activated, false otherwise
*/
public static boolean isDisableStaticDialogScrolling() {
return disableStaticDialogScrolling;
}
/**
* Places commands as buttons at the bottom of the standard static dialogs rather than
* as softbuttons. This is especially appropriate for devices such as touch devices and
* devices without the common softbuttons (e.g. blackberries).
* The default value is false
*
* @param c true to place commands as buttons and not as softbutton keys
*/
public static void setCommandsAsButtons(boolean c) {
commandsAsButtons = c;
}
/**
* Places commands as buttons at the bottom of the standard static dialogs rather than
* as softbuttons. This is especially appropriate for devices such as touch devices and
* devices without the common softbuttons (e.g. blackberries).
* The default value is false
*
* @return true if commands are placed as buttons and not as softbutton keys
*/
public static boolean isCommandsAsButtons() {
return commandsAsButtons;
}
/**
* This flag indicates if the dialog should be disposed if a pointer
* released event occurred out of the dialog content.
*
* @param disposeWhenPointerOutOfBounds
*/
public void setDisposeWhenPointerOutOfBounds(boolean disposeWhenPointerOutOfBounds) {
this.disposeWhenPointerOutOfBounds = disposeWhenPointerOutOfBounds;
}
/**
* This flag indicates if the dialog should be disposed if a pointer
* released event occurred out of the dialog content.
*
* @return true if the dialog should dispose
*/
public boolean isDisposeWhenPointerOutOfBounds() {
return disposeWhenPointerOutOfBounds;
}
/**
* {@inheritDoc}
*/
public void pointerReleased(int x, int y) {
super.pointerReleased(x, y);
if(disposeWhenPointerOutOfBounds &&
pressedOutOfBounds &&
!getTitleComponent().containsOrOwns(x, y) &&
!getContentPane().containsOrOwns(x, y) &&
!getMenuBar().containsOrOwns(x, y)){
dispose();
}
}
/**
* {@inheritDoc}
*/
public void pointerPressed(int x, int y) {
super.pointerPressed(x, y);
if(!getTitleComponent().containsOrOwns(x, y) &&
!getContentPane().containsOrOwns(x, y) &&
!getMenuBar().containsOrOwns(x, y)){
pressedOutOfBounds = true;
}else{
pressedOutOfBounds = false;
}
}
/**
* Returns true if a dialog that was disposed did it because of a pointer out of bounds
* @return true when a dialog was disposed due to pointer out of bounds.
*/
public boolean wasDisposedDueToOutOfBoundsTouch() {
return pressedOutOfBounds;
}
/**
* Screen orientation position for the upcoming dialog. By default
* the dialog will be shown at hardcoded coordinates, this method allows us
* to pack the dialog appropriately in one of the border layout based locations
* see BorderLayout for futher details.
* @return the dialogPosition
*/
public String getDialogPosition() {
return dialogPosition;
}
/**
* Screen orientation position for the upcoming dialog. By default
* the dialog will be shown at hardcoded coordinates, this method allows us
* to pack the dialog appropriately in one of the border layout based locations
* see BorderLayout for futher details.
* @param dialogPosition the dialogPosition to set
*/
public void setDialogPosition(String dialogPosition) {
this.dialogPosition = dialogPosition;
}
/**
* {@inheritDoc}
*/
void repaint(Component cmp) {
if(getParent() != null){
super.repaint(cmp);
return;
}
if (isVisible() && !disposed && (isMenu() || CN.getCurrentForm() == this)) {
Display.getInstance().repaint(cmp);
}
}
/**
* Allows a dialog component to grow or shrink to its new preferred size
*/
public void growOrShrink() {
getDialogComponent().setShouldCalcPreferredSize(true);
growOrShrinkImpl(Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight());
forceRevalidate();
}
private void growOrShrinkImpl(int w, int h) {
Component contentPane = super.getContentPane();
Component title = super.getTitleComponent();
int prefHeight = contentPane.getPreferredH();
int prefWidth = contentPane.getPreferredW();
Style contentPaneStyle = contentPane.getStyle();
Style titleStyle = title.getStyle();
// if the dialog is packed we can scale it far more accurately based on intention
if (position != null) {
int menuHeight = 0;
if (getSoftButtonCount() > 1) {
Component menuBar = getSoftButton(0).getParent();
Style menuStyle = menuBar.getStyle();
menuHeight = menuBar.getPreferredH() + menuStyle.getVerticalMargins();
}
prefWidth = Math.min(prefWidth, w);
h = h - menuHeight - title.getPreferredH();// - titleStyle.getMargin(false, TOP) - titleStyle.getMargin(false, BOTTOM);
int topBottom = Math.max(0, (h - prefHeight) / 2);
int leftRight = Math.max(0, (w - prefWidth) / 2);
int top = topBottom, bottom = topBottom;
int left = leftRight, right = leftRight;
if (position.equals(BorderLayout.EAST)) {
left = Math.max(0, w - prefWidth);
right = 0;
} else {
if (position.equals(BorderLayout.WEST)) {
right = 0;
left = Math.max(0, w - prefWidth);
} else {
if (position.equals(BorderLayout.NORTH)) {
top = 0;
bottom = Math.max(0, h - prefHeight);
} else {
if (position.equals(BorderLayout.SOUTH)) {
top = Math.max(0, h - prefHeight);
bottom = 0;
}
}
}
}
titleStyle.setMargin(Component.TOP, 0, true);
titleStyle.setMargin(Component.BOTTOM, 0, true);
titleStyle.setMargin(Component.LEFT, 0, true);
titleStyle.setMargin(Component.RIGHT, 0, true);
contentPaneStyle.setMargin(Component.TOP, top, true);
contentPaneStyle.setMargin(Component.BOTTOM, bottom, true);
contentPaneStyle.setMargin(Component.LEFT, left, true);
contentPaneStyle.setMargin(Component.RIGHT, right, true);
return;
} else {
int oldW = getWidth();
int oldH = getHeight();
if (oldW != w || oldH != h) {
// try to preserve the old size of the dialog if we still have room for it...
if(prefWidth <= w && prefHeight <= h) {
float oldLeftRightDistRatio = 1;
if(left + right != 0) {
oldLeftRightDistRatio = ((float)left) / ((float)left + right);
}
float oldTopBottomDistRatio = 1;
if(left + right != 0) {
oldTopBottomDistRatio = ((float)top) / ((float)top + bottom);
}
top = Math.max(0, (int)((h - prefHeight) * oldTopBottomDistRatio));
left = Math.max(0, (int)((w - prefWidth) * oldLeftRightDistRatio));
bottom = Math.max(0, (h - prefHeight) - top);
right = Math.max(0, (w - prefWidth) - left);
titleStyle.setMargin(Component.TOP, 0, true);
titleStyle.setMargin(Component.BOTTOM, 0, true);
titleStyle.setMargin(Component.LEFT, 0, true);
titleStyle.setMargin(Component.RIGHT, 0, true);
contentPaneStyle.setMargin(Component.TOP, top, true);
contentPaneStyle.setMargin(Component.BOTTOM, bottom, true);
contentPaneStyle.setMargin(Component.LEFT, left, true);
contentPaneStyle.setMargin(Component.RIGHT, right, true);
return;
} else {
float ratioW = ((float) w) / ((float) oldW);
float ratioH = ((float) h) / ((float) oldH);
Style s = getDialogStyle();
s.setMargin(TOP, (int) (s.getMarginTop() * ratioH));
s.setMargin(BOTTOM, (int) (s.getMarginBottom() * ratioH));
s.setMargin(LEFT, (int) (s.getMarginLeft(isRTL()) * ratioW));
s.setMargin(RIGHT, (int) (s.getMarginRight(isRTL()) * ratioW));
titleStyle.setMargin(TOP, (int) (titleStyle.getMarginTop() * ratioH));
titleStyle.setMargin(LEFT, (int) (titleStyle.getMarginLeft(isRTL()) * ratioW));
titleStyle.setMargin(RIGHT, (int) (titleStyle.getMarginRight(isRTL()) * ratioW));
return;
}
}
}
}
/**
* Indicates if we want to enforce directional bias for the popup dialog. If null this field is ignored but if
* its set to a value it biases the system towards a fixed direction for the popup dialog.
* @return the popupDirectionBiasPortrait
*/
public Boolean getPopupDirectionBiasPortrait() {
return popupDirectionBiasPortrait;
}
/**
* Indicates if we want to enforce directional bias for the popup dialog. If null this field is ignored but if
* its set to a value it biases the system towards a fixed direction for the popup dialog.
* @param popupDirectionBiasPortrait the popupDirectionBiasPortrait to set
*/
public void setPopupDirectionBiasPortrait(Boolean popupDirectionBiasPortrait) {
this.popupDirectionBiasPortrait = popupDirectionBiasPortrait;
}
/**
* Returns true if the dialog was disposed automatically due to device rotation
* @return the disposedDueToRotation value
*/
public boolean wasDisposedDueToRotation() {
return disposedDueToRotation;
}
/**
* Dialog background can be blurred using a Gaussian blur effect, this sets the radius of the Gaussian
* blur. -1 is a special case value that indicates that no blurring should take effect and the default tint mode
* only should be used
* @return the blurBackgroundRadius
*/
public float getBlurBackgroundRadius() {
return blurBackgroundRadius;
}
/**
* Dialog background can be blurred using a Gaussian blur effect, this sets the radius of the Gaussian
* blur. -1 is a special case value that indicates that no blurring should take effect and the default tint mode
* only should be used. Notice that this value can be set using the theme constant: {@code dialogBlurRadiusInt}
* @param blurBackgroundRadius the blurBackgroundRadius to set
*/
public void setBlurBackgroundRadius(float blurBackgroundRadius) {
this.blurBackgroundRadius = blurBackgroundRadius;
}
/**
* Dialog background can be blurred using a Gaussian blur effect, this sets the radius of the Gaussian
* blur. -1 is a special case value that indicates that no blurring should take effect and the default tint mode
* only should be used
* @return the defaultBlurBackgroundRadius
*/
public static float getDefaultBlurBackgroundRadius() {
return defaultBlurBackgroundRadius;
}
/**
* Dialog background can be blurred using a Gaussian blur effect, this sets the radius of the Gaussian
* blur. -1 is a special case value that indicates that no blurring should take effect and the default tint mode
* only should be used. Notice that this value can be set using the theme constant: {@code dialogBlurRadiusInt}
* @param aDefaultBlurBackgroundRadius the defaultBlurBackgroundRadius to set
*/
public static void setDefaultBlurBackgroundRadius(float aDefaultBlurBackgroundRadius) {
defaultBlurBackgroundRadius = aDefaultBlurBackgroundRadius;
}
/**
* In case of a blur effect we need to do something different...
* {@inheritDoc}
*/
void initDialogBgPainter(Painter p, Form previousForm) {
if(getBlurBackgroundRadius() > 0 && Display.impl.isGaussianBlurSupported()) {
Image img = Image.createImage(previousForm.getWidth(), previousForm.getHeight());
Graphics g = img.getGraphics();
previousForm.paintComponent(g, true);
img = Display.getInstance().gaussianBlurImage(img, blurBackgroundRadius);
getUnselectedStyle().setBgImage(img);
getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
} else {
super.initDialogBgPainter(p, previousForm);
}
}
/**
* Allows to use the UIIDs "PopupContentPaneDownwards",
* "PopupContentPaneUpwards", "PopupContentPaneRight",
* "PopupContentPaneLeft" (instead of the default UIID "PopupContentPane")
* to style the PopupDialog more accurately based on the position of the
* dialog popup compared to the context component.
*
* @param b to enable
*/
public void setUIIDByPopupPosition(boolean b) {
this.isUIIDByPopupPosition = b;
}
}