
com.codename1.impl.javase.JavaSEPort 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.impl.javase;
import com.codename1.background.BackgroundFetch;
import com.codename1.capture.VideoCaptureConstraints;
import com.codename1.charts.util.ColorUtil;
import com.codename1.components.SpanLabel;
import com.codename1.components.ToastBar;
import com.codename1.contacts.Address;
import com.codename1.contacts.Contact;
import com.codename1.db.Database;
import com.codename1.impl.javase.simulator.*;
import com.codename1.impl.javase.util.MavenUtils;
import com.codename1.impl.javase.util.SwingUtils;
import com.codename1.messaging.Message;
import com.codename1.ui.Component;
import com.codename1.ui.Display;
import com.codename1.ui.Font;
import com.codename1.ui.Form;
import com.codename1.ui.Graphics;
import com.codename1.ui.Image;
import com.codename1.impl.CodenameOneImplementation;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.EventDispatcher;
import com.codename1.ui.util.Resources;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.FontFormatException;
import javax.swing.JFrame;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.FilenameFilter;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URI;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import com.codename1.io.Properties;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.prefs.Preferences;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.imageio.ImageIO;
import javax.imageio.stream.MemoryCacheImageInputStream;
import com.codename1.io.BufferedInputStream;
import com.codename1.io.BufferedOutputStream;
import com.codename1.io.ConnectionRequest;
import com.codename1.io.FileSystemStorage;
import com.codename1.io.Log;
import com.codename1.io.NetworkManager;
import com.codename1.io.Storage;
import com.codename1.io.Util;
import com.codename1.l10n.L10NManager;
import com.codename1.location.Location;
import com.codename1.location.LocationManager;
import com.codename1.media.AbstractMedia;
import com.codename1.media.AudioBuffer;
import com.codename1.media.Media;
import com.codename1.media.MediaManager;
import com.codename1.media.MediaRecorderBuilder;
import com.codename1.notifications.LocalNotification;
import com.codename1.payment.Product;
import com.codename1.payment.Purchase;
import com.codename1.payment.Receipt;
import com.codename1.ui.Accessor;
import com.codename1.ui.BrowserWindow;
import com.codename1.ui.CN;
import com.codename1.ui.ComponentSelector;
import com.codename1.ui.EncodedImage;
import com.codename1.ui.FontImage;
import com.codename1.ui.PeerComponent;
import com.codename1.ui.Sheet;
import com.codename1.ui.TextArea;
import com.codename1.ui.TextSelection;
import com.codename1.ui.Transform;
import com.codename1.ui.plaf.Style;
import com.codename1.ui.util.UITimer;
import com.codename1.util.AsyncResource;
import com.codename1.util.Callback;
import com.jhlabs.image.GaussianFilter;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.sql.DriverManager;
import java.text.AttributedString;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.*;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import javax.swing.plaf.SplitPaneUI;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import javax.swing.text.DefaultCaret;
import javax.swing.text.JTextComponent;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import com.jhlabs.image.ShadowFilter;
import org.sqlite.SQLiteConfig;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import static com.codename1.impl.javase.util.MavenUtils.isRunningInMaven;
/**
* An implementation of Codename One based on Java SE
*
* @author Shai Almog
*/
public class JavaSEPort extends CodenameOneImplementation {
private static final int ICON_SIZE=24;
public final static boolean IS_MAC;
private static boolean isIOS;
public static boolean blockNativeBrowser;
private static final boolean isWindows;
private static String fontFaceSystem;
private Boolean darkMode;
/**
* @return the fullScreen
*/
public static boolean isFullScreen() {
return fullScreen;
}
/**
* @param aFullScreen the fullScreen to set
*/
public static void setFullScreen(boolean aFullScreen) {
fullScreen = aFullScreen;
}
private JFrame findTopFrame() {
java.awt.Component c = canvas;
return (JFrame)canvas.getTopLevelAncestor();
/*
if (c == null) return null;
while (c.getParent() != null) {
c = c.getParent();
if (c instanceof JFrame) {
return (JFrame)c;
}
}
return null;
*/
}
@Override
public boolean isFullScreenSupported() {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
boolean desktopSkin = pref.getBoolean("desktopSkin", false);
if (isSimulator() && !desktopSkin) {
return false;
}
return true;
}
private java.awt.Rectangle restoreWindowBounds;
@Override
public boolean requestFullScreen() {
if (!isFullScreenSupported()) return false;
if (!fullScreen) {
if (!EventQueue.isDispatchThread()) {
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
requestFullScreen();
}
});
} catch (InterruptedException ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
}
return fullScreen;
}
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
JFrame frm = findTopFrame();
if (frm == null) {
return false;
}
if(gd.isFullScreenSupported()) {
restoreWindowBounds = frm.getBounds();
frm.dispose();
frm.setUndecorated(true);
frm.setResizable(false);
gd.setFullScreenWindow(frm);
}
fullScreen = true;
}
return fullScreen;
}
@Override
public boolean exitFullScreen() {
if (!isFullScreenSupported()) return false;
if (fullScreen) {
if (!EventQueue.isDispatchThread()) {
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
exitFullScreen();
}
});
} catch (InterruptedException ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
}
return !fullScreen;
}
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
JFrame frm = findTopFrame();
if (frm == null) {
return false;
}
if(gd.isFullScreenSupported()) {
frm.dispose();
frm.setUndecorated(false);
frm.setResizable(true);
gd.setFullScreenWindow(null);
if (restoreWindowBounds != null) {
frm.setBounds(restoreWindowBounds);
} else {
frm.setBounds(new java.awt.Rectangle(0, 0, 800, 600));
}
frm.setVisible(true);
}
fullScreen = false;
}
return !fullScreen;
}
@Override
public boolean isInFullScreenMode() {
return fullScreen;
}
@Override
public Boolean isDarkMode() {
return darkMode;
}
public boolean takingScreenshot;
private static boolean fullScreen;
public float screenshotActualZoomLevel;
private InputEvent lastInputEvent;
public static double retinaScale = 1.0;
static JMenuItem pause;
private static int cachedJavaVersion=-1;
/**
* Returns the Java version as an int value.
*
* @return the Java version as an int value (8, 9, etc.)
* @since 12130
*/
private static int getJavaVersion() {
if (cachedJavaVersion < 0) {
String version = System.getProperty("java.version");
if (version.startsWith("1.")) {
version = version.substring(2);
}
// Allow these formats:
// 1.8.0_72-ea
// 9-ea
// 9
// 9.0.1
int dotPos = version.indexOf('.');
int dashPos = version.indexOf('-');
if (dotPos < 0 && dashPos < 0) {
cachedJavaVersion = Integer.parseInt(version);
return cachedJavaVersion;
}
cachedJavaVersion = Integer.parseInt(version.substring(0,
dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : 1));
return cachedJavaVersion;
}
return cachedJavaVersion;
}
public static boolean isRetina() {
boolean isRetina = false;
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
try {
if (getJavaVersion() >= 9) {
// JDK9 Doesn't like the old hack for getting the scale via reflection.
// https://bugs.openjdk.java.net/browse/JDK-8172962
GraphicsConfiguration graphicsConfig = graphicsDevice
.getDefaultConfiguration();
AffineTransform tx = graphicsConfig.getDefaultTransform();
double scaleX = tx.getScaleX();
double scaleY = tx.getScaleY();
if (scaleX >= 2 && scaleY >= 2) {
isRetina = true;
}
} else {
Field field = graphicsDevice.getClass().getDeclaredField("scale");
if (field != null) {
field.setAccessible(true);
Object scale = field.get(graphicsDevice);
if (scale instanceof Integer && ((Integer) scale).intValue() >= 2) {
isRetina = true;
}
}
}
} catch (Throwable e) {
//e.printStackTrace();
}
return isRetina;
}
public static double calcRetinaScale() {
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
try {
if (getJavaVersion() >= 9) {
// JDK9 Doesn't like the old hack for getting the scale via reflection.
// https://bugs.openjdk.java.net/browse/JDK-8172962
GraphicsConfiguration graphicsConfig = graphicsDevice
.getDefaultConfiguration();
AffineTransform tx = graphicsConfig.getDefaultTransform();
double scaleX = tx.getScaleX();
double scaleY = tx.getScaleY();
return Math.max(1.0, Math.min(scaleX, scaleY));
} else {
Field field = graphicsDevice.getClass().getDeclaredField("scale");
if (field != null) {
field.setAccessible(true);
Object scale = field.get(graphicsDevice);
if (scale instanceof Integer && ((Integer) scale).intValue() >= 2) {
return ((Integer)scale).doubleValue();
}
}
}
} catch (Throwable e) {
//e.printStackTrace();
}
return 1.0;
}
public static double getRetinaScale() {
return retinaScale;
}
/**
* When set to true pointer hover events will be called for mouse move events
*/
private static boolean invokePointerHover;
private static String defaultCodenameOneComProtocol = "https";
static {
String n = System.getProperty("os.name");
if (n != null && n.startsWith("Mac")) {
IS_MAC = true;
} else {
IS_MAC = false;
}
isWindows = File.separatorChar == '\\';
System.setProperty("apple.laf.useScreenMenuBar", "true");
if(isWindows) {
fontFaceSystem = "ArialUnicodeMS";
} else {
fontFaceSystem = "Arial";
}
}
/**
* When set to true pointer hover events will be called for mouse move events
* @return the invokePointerHover
*/
public static boolean isInvokePointerHover() {
return invokePointerHover;
}
/**
* When set to true pointer hover events will be called for mouse move events
* @param aInvokePointerHover the invokePointerHover to set
*/
public static void setInvokePointerHover(boolean aInvokePointerHover) {
invokePointerHover = aInvokePointerHover;
}
private boolean minimized;
//private javafx.embed.swing.JFXPanel mediaContainer;
private static File baseResourceDir;
private static final String DEFAULT_SKIN = "/iPhoneX.skin";
private static final String DEFAULT_SKINS = DEFAULT_SKIN+";";
private static String appHomeDir = ".cn1";
/**
* Allowed video extensions for the gallery.
*/
private String[] videoExtensions = new String[] {
"mp4", "h264", "3pg", "mov", "scmov", "gbmov",
"f4v", "m2ts", "mts", "ts", "wmv", "vob", "m4v",
"flv", "mod", "mkv", "avi", "mpg", "3gp"
};
/**
* Allowed image extensions for the gallery.
*/
private String[] imageExtensions = new String[] {"png", "jpg", "jpeg"};
private boolean menuDisplayed = false;
private static boolean android6PermissionsFlag = false;
private static boolean waitForPermission = false;
private static Map android6Permissions = new HashMap();
/**
* Allows the simulator to use the native filesystem completely rather than the "fake" filesystem
* used, this is important when running a real application rather than just a simulator skin
* @return the exposeFilesystem
*/
public static boolean isExposeFilesystem() {
return exposeFilesystem;
}
/**
* Allows the simulator to use the native filesystem completely rather than the "fake" filesystem
* used, this is important when running a real application rather than just a simulator skin
* @param aExposeFilesystem the exposeFilesystem to set
*/
public static void setExposeFilesystem(boolean aExposeFilesystem) {
exposeFilesystem = aExposeFilesystem;
}
/**
* @return the designMode
*/
public static boolean isDesignMode() {
return designMode;
}
/**
* @param aDesignMode the designMode to set
*/
public static void setDesignMode(boolean aDesignMode) {
designMode = aDesignMode;
}
public int getDeviceDensity() {
if(defaultPixelMilliRatio != null) {
/*
if(Math.round(defaultPixelMilliRatio.doubleValue()) == 10) {
return Display.DENSITY_MEDIUM;
}
if(Math.round(defaultPixelMilliRatio.doubleValue()) == 20) {
return Display.DENSITY_VERY_HIGH;
}
System.out.println("Ratio "+defaultPixelMilliRatio.doubleValue());
*/
if (retinaScale > 1.5) {
return Display.DENSITY_VERY_HIGH;
} else {
return Display.DENSITY_MEDIUM;
}
}
return super.getDeviceDensity();
}
/**
* @return the defaultPixelMilliRatio
*/
public static Double getDefaultPixelMilliRatio() {
return defaultPixelMilliRatio;
}
/**
* @param aDefaultPixelMilliRatio the defaultPixelMilliRatio to set
*/
public static void setDefaultPixelMilliRatio(Double aDefaultPixelMilliRatio) {
defaultPixelMilliRatio = aDefaultPixelMilliRatio;
}
/**
* @return the appHomeDir
*/
public static String getAppHomeDir() {
return appHomeDir;
}
/**
* @param aAppHomeDir the appHomeDir to set
*/
public static void setAppHomeDir(String aAppHomeDir) {
appHomeDir = aAppHomeDir;
}
protected TestRecorder testRecorder;
private Hashtable contacts;
private static boolean designMode;
/**
* @return the showEDTWarnings
*/
public static boolean isShowEDTWarnings() {
return showEDTWarnings;
}
@Override
public void setPlatformHint(String key, String value) {
if (key.equalsIgnoreCase("platformHint.showEDTWarnings")) {
setShowEDTWarnings("true".equalsIgnoreCase(value));
}
super.setPlatformHint(key, value);
}
/**
* @param aShowEDTWarnings the showEDTWarnings to set
*/
public static void setShowEDTWarnings(boolean aShowEDTWarnings) {
showEDTWarnings = aShowEDTWarnings;
}
/**
* @return the showEDTViolationStacks
*/
public static boolean isShowEDTViolationStacks() {
return showEDTViolationStacks;
}
/**
* @param aShowEDTViolationStacks the showEDTViolationStacks to set
*/
public static void setShowEDTViolationStacks(boolean aShowEDTViolationStacks) {
showEDTViolationStacks = aShowEDTViolationStacks;
}
private boolean touchDevice = true;
private boolean rotateTouchKeysOnLandscape;
private int keyboardType = Display.KEYBOARD_TYPE_UNKNOWN;
private static int medianFontSize = 15;
private static int smallFontSize = 11;
private static int largeFontSize = 19;
static {
retinaScale = calcRetinaScale();
if (System.getProperty("cn1.retinaScale", null) != null) {
try {
retinaScale = Double.parseDouble(System.getProperty("cn1.retinaScale"));
} catch (Throwable t){}
} else if (System.getenv("CN1_RETINA_SCALE") != null) {
try {
retinaScale = Double.parseDouble(System.getenv("CN1_RETINA_SCALE"));
} catch (Throwable t) {}
}
System.out.println("Retina Scale: "+retinaScale);
if (retinaScale > 1.5) {
medianFontSize = (int)(medianFontSize * retinaScale);
smallFontSize = (int)(smallFontSize * retinaScale);
largeFontSize = (int)(largeFontSize * retinaScale);
}
}
private static String fontFaceProportional = "SansSerif";
private static String fontFaceMonospace = "Monospaced";
private static boolean alwaysOnTop = false;
private static boolean useNativeInput = true;
private static boolean simulateAndroidKeyboard = false;
private static boolean scrollableSkin = false;
protected JScrollBar hSelector = new JScrollBar(Scrollbar.HORIZONTAL);
protected JScrollBar vSelector = new JScrollBar(Scrollbar.VERTICAL);
static final int GAME_KEY_CODE_FIRE = -90;
static final int GAME_KEY_CODE_UP = -91;
static final int GAME_KEY_CODE_DOWN = -92;
static final int GAME_KEY_CODE_LEFT = -93;
static final int GAME_KEY_CODE_RIGHT = -94;
private static String nativeTheme;
private static Resources nativeThemeRes;
private static int softkeyCount = 1;
private static boolean tablet;
private static String DEFAULT_FONT = "Arial-plain-11";
private static EventDispatcher formChangeListener;
private static boolean autoAdjustFontSize = true;
private static Object defaultInitTarget;
public float zoomLevel = 1;
private File storageDir;
// skin related variables
private boolean portrait = true;
private BufferedImage portraitSkin;
private BufferedImage landscapeSkin;
private boolean roundedSkin;
private Rectangle safeAreaPortrait = null;
private Rectangle safeAreaLandscape = null;
private Map portraitSkinHotspots;
private java.awt.Rectangle portraitScreenCoordinates;
private Map landscapeSkinHotspots;
private java.awt.Rectangle landscapeScreenCoordinates;
private static Class clsInstance;
private BufferedImage header;
private BufferedImage headerLandscape;
private String platformName = "ios";
private String[] platformOverrides = new String[0];
private static NetworkMonitor netMonitor;
private ComponentTreeInspector componentTreeInspector;
private static PerformanceMonitor perfMonitor;
static LocationSimulation locSimulation;
static PushSimulator pushSimulation;
private static boolean blockMonitors;
private static boolean useAppFrame = Boolean.getBoolean("cn1.simulator.useAppFrame");
static {
try {
if (useAppFrame) {
// If the app frame is enabled in System properties, it can be disabled
// by the user preferences.
// If the system property is false, however, then it should not be overridden
// by the preference. The app frame must be DOUBLE activated - in system property
// and preferences to be active to prevent it from accendentally being enabled
// in other contexts, like unit tests or desktop app distributions.
Preferences prefs = Preferences.userNodeForPackage(JavaSEPort.class);
useAppFrame = prefs.getBoolean("cn1.simulator.useAppFrame", useAppFrame);
}
} catch (Exception ex){}
}
protected static boolean fxExists = false;
private JFrame window;
// Application frame used for simulator
private AppFrame appFrame;
private long lastIdleTime;
private static boolean showEDTWarnings = true;
private static boolean showEDTViolationStacks = false;
private boolean inInit;
private boolean showMenu = true;
private static Double defaultPixelMilliRatio;
private Double pixelMilliRatio = defaultPixelMilliRatio;
private boolean manualPurchaseSupported;
private boolean managedPurchaseSupported;
private boolean subscriptionSupported;
private boolean refundSupported;
private int timeout = -1;
private JLabel widthLabel;
private JLabel heightLabel;
private boolean includeHeaderInScreenshot = true;
private boolean includeSkinInScreenshot = false;
private boolean slowConnectionMode;
private boolean disconnectedMode;
private static boolean exposeFilesystem;
private boolean scrollWheeling;
private JComponent textCmp;
private java.util.Timer backgroundFetchTimer;
private void startBackgroundFetchService() {
if (isBackgroundFetchSupported()) {
checkIosBackgroundFetch();
stopBackgroundFetchService();
if (getPreferredBackgroundFetchInterval() > 0) {
backgroundFetchTimer = new java.util.Timer();
TimerTask tt = new TimerTask() {
@Override
public void run() {
performBackgroundFetch();
}
};
backgroundFetchTimer.schedule(tt, getPreferredBackgroundFetchInterval() * 1000, getPreferredBackgroundFetchInterval() * 1000);
}
}
}
private void stopBackgroundFetchService() {
if (isBackgroundFetchSupported()) {
if (backgroundFetchTimer != null) {
backgroundFetchTimer.cancel();
backgroundFetchTimer = null;
}
}
}
@Override
public boolean isBackgroundFetchSupported() {
return Display.getInstance().isSimulator();
}
private boolean backgroundFetchInitialized;
@Override
public void setPreferredBackgroundFetchInterval(int seconds) {
if (isBackgroundFetchSupported()) {
int oldInterval = getPreferredBackgroundFetchInterval();
super.setPreferredBackgroundFetchInterval(seconds);
if (!backgroundFetchInitialized || oldInterval != seconds) {
backgroundFetchInitialized = true;
startBackgroundFetchService();
}
}
}
private static void performBackgroundFetch() {
if (Display.getInstance().isMinimized()) {
// By definition, background fetch should only occur if the app is minimized.
// This keeps it consistent with the iOS implementation that doesn't have a
// choice
final Object lifecycle = Executor.getApp();
final boolean completed[] = new boolean[1];
final java.util.Timer t = new java.util.Timer();
final java.util.TimerTask overtimeChecker = new TimerTask() {
public void run() {
if (!completed[0]) {
com.codename1.io.Log.p("WARNING: performBackgroundFetch() was called over 30 seconds ago and has not called its completion callback. This may cause problems on iOS devices. performBackgroundFetch() must complete in under 30 seconds and call the completion callback when done.");
}
}
};
if (lifecycle instanceof BackgroundFetch) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
// In callSerially
t.schedule(overtimeChecker, 30*60*1000);
((BackgroundFetch)lifecycle).performBackgroundFetch(System.currentTimeMillis()+25*60*1000, new Callback() {
@Override
public void onSucess(Boolean value) {
// On JavaSE the OS doesn't care whether it worked or not
// So we'll just consume this.
completed[0] = true;
}
@Override
public void onError(Object sender, Throwable err, int errorCode, String errorMessage) {
completed[0] = false;
com.codename1.io.Log.e(err);
}
});
}
});
}
}
}
private static long getRepeatPeriod(int repeat) {
switch (repeat) {
case LocalNotification.REPEAT_DAY:
return 24 * 60 * 60 * 1000L;
case LocalNotification.REPEAT_HOUR:
return 60 * 60 * 1000L;
case LocalNotification.REPEAT_MINUTE:
return 60 * 1000L;
case LocalNotification.REPEAT_WEEK:
return 7 * 24 * 60 * 60 * 1000L;
default:
return 0L;
}
}
private Map localNotifications = new HashMap();
private java.util.Timer localNotificationsTimer;
@Override
public void scheduleLocalNotification(final LocalNotification notif, long firstTime, int repeat) {
if (isSimulator()) {
if (localNotificationsTimer == null) {
localNotificationsTimer = new java.util.Timer();
}
TimerTask task = new TimerTask() {
public void run() {
if (!SystemTray.isSupported()) {
System.out.println("Local notification not supported on this OS!!!");
return;
}
if (isMinimized()) {
SystemTray sysTray = SystemTray.getSystemTray();
TrayIcon tray = new TrayIcon(Toolkit.getDefaultToolkit().getImage("/CodenameOne_Small.png"));
tray.setImageAutoSize(true);
tray.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
Executor.startApp();
minimized = false;
}
});
canvas.setEnabled(true);
pause.setText("Pause App");
}
});
try {
sysTray.add(tray);
tray.displayMessage(notif.getAlertTitle(), notif.getAlertBody(), TrayIcon.MessageType.INFO);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
};
if (localNotifications.containsKey(notif.getId())) {
TimerTask old = localNotifications.get(notif.getId());
old.cancel();
}
localNotifications.put(notif.getId(), task);
if (repeat == LocalNotification.REPEAT_NONE) {
localNotificationsTimer.schedule(task, new Date(firstTime));
} else {
localNotificationsTimer.schedule(task, new Date(firstTime), getRepeatPeriod(repeat));
}
}
}
@Override
public void cancelLocalNotification(String notificationId) {
if (isSimulator()) {
if (localNotifications.containsKey(notificationId)) {
TimerTask n = localNotifications.get(notificationId);
n.cancel();
localNotifications.remove(notificationId);
}
}
}
public static void blockMonitors() {
blockMonitors = true;
}
public static void useAppFrame() {
useAppFrame = true;
}
static void disableNetworkMonitor() {
netMonitor = null;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("NetworkMonitor", false);
}
static void disablePerformanceMonitor() {
perfMonitor = null;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("PerformanceMonitor", false);
}
class EDTViolation extends Exception {
public EDTViolation() {
super("EDT Violation Stack!");
}
}
private void checkEDT() {
if (isShowEDTWarnings() && !Display.getInstance().isEdt() && !inInit) {
System.out.println("EDT violation detected!");
if (isShowEDTViolationStacks()) {
new EDTViolation().printStackTrace();
}
}
}
public static void setBaseResourceDir(File f) {
baseResourceDir = f;
}
public static void setClassLoader(Class cls) {
clsInstance = cls;
}
public static Class getClassLoader() {
return clsInstance;
}
public static void setDefaultInitTarget(Object o) {
defaultInitTarget = o;
}
private Map getSkinHotspots() {
if (portrait) {
return portraitSkinHotspots;
}
return landscapeSkinHotspots;
}
public java.awt.Rectangle getScreenCoordinates() {
if (portrait) {
return portraitScreenCoordinates;
}
return landscapeScreenCoordinates;
}
private BufferedImage getSkin() {
if (portrait) {
return portraitSkin;
}
return landscapeSkin;
}
public static void setAutoAdjustFontSize(boolean autoAdjustFontSize_) {
autoAdjustFontSize = autoAdjustFontSize_;
}
public static void setFontSize(int medium, int small, int large) {
medianFontSize = medium;
smallFontSize = small;
largeFontSize = large;
DEFAULT_FONT = fontFaceSystem + "-plain-" + medium;
autoAdjustFontSize = false;
}
public static void setFontFaces(String system, String proportional, String monospace) {
fontFaceSystem = system;
fontFaceProportional = proportional;
fontFaceMonospace = monospace;
DEFAULT_FONT = fontFaceSystem + "-plain-" + medianFontSize;
autoAdjustFontSize = false;
}
/**
* This is useful for debugging tools used in software automation
*/
public static void addFormChangeListener(com.codename1.ui.events.ActionListener al) {
if (formChangeListener == null) {
formChangeListener = new EventDispatcher();
}
formChangeListener.addListener(al);
}
@Override
public void copyToClipboard(Object obj) {
if (obj instanceof String) {
final String text = (String)obj;
EventQueue.invokeLater(new Runnable() {
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Clipboard clipboard = toolkit.getSystemClipboard();
StringSelection strSel = new StringSelection(text.trim());
clipboard.setContents(strSel, null);
}
});
} else {
final String text = "cn1lightweightclipboard://"+obj.toString();
EventQueue.invokeLater(new Runnable() {
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Clipboard clipboard = toolkit.getSystemClipboard();
StringSelection strSel = new StringSelection(text.trim());
clipboard.setContents(strSel, null);
}
});
}
super.copyToClipboard(obj); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Object getPasteDataFromClipboard() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Clipboard clipboard = toolkit.getSystemClipboard();
for (DataFlavor flavor : clipboard.getAvailableDataFlavors()) {
try {
Object out = clipboard.getData(flavor);
String str = null;
if (out != null) {
str = out.toString();
}
if (str != null && str.startsWith("cn1lightweightclipboard://")) {
return super.getPasteDataFromClipboard();
}
} catch (Exception ex) {
}
}
for (DataFlavor flavor : clipboard.getAvailableDataFlavors()) {
try {
Object out = clipboard.getData(flavor);
if (out != null) {
String str = out.toString();
if (str != null) return str;
}
} catch (Exception ex) {
}
}
return super.getPasteDataFromClipboard();
}
public void setCurrentForm(Form f) {
super.setCurrentForm(f);
if (formChangeListener != null) {
formChangeListener.fireActionEvent(new com.codename1.ui.events.ActionEvent(f));
}
}
public static void setNativeTheme(String resFile) {
nativeTheme = resFile;
}
public static void setNativeTheme(Resources resFile) {
nativeThemeRes = resFile;
}
@Override
public boolean isSetCursorSupported() {
return true;
}
public static Resources getNativeTheme() {
return nativeThemeRes;
}
public boolean hasNativeTheme() {
return nativeTheme != null || nativeThemeRes != null;
}
public void installNativeTheme() {
checkEDT();
if (nativeTheme != null) {
try {
Resources r = Resources.open(nativeTheme);
Hashtable h = r.getTheme(r.getThemeResourceNames()[0]);
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
boolean desktopSkin = pref.getBoolean("desktopSkin", false);
if(desktopSkin) {
safeAreaLandscape = null;
safeAreaPortrait = null;
h.remove("@paintsTitleBarBool");
}
UIManager.getInstance().setThemeProps(h);
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
if (nativeThemeRes != null) {
UIManager.getInstance().setThemeProps(nativeThemeRes.getTheme(nativeThemeRes.getThemeResourceNames()[0]));
}
}
}
/**
* @return the useNativeInput
*/
public static boolean isUseNativeInput() {
return useNativeInput;
}
/**
* @param aUseNativeInput the useNativeInput to set
*/
public static void setUseNativeInput(boolean aUseNativeInput) {
useNativeInput = aUseNativeInput;
}
/**
* @param aSoftkeyCount the softkeyCount to set
*/
public static void setSoftkeyCount(int aSoftkeyCount) {
softkeyCount = aSoftkeyCount;
}
@Override
public boolean isRightMouseButtonDown() {
if (lastInputEvent != null) {
if (lastInputEvent instanceof MouseEvent) {
MouseEvent me = (MouseEvent) lastInputEvent;
return SwingUtilities.isRightMouseButton(me);
}
}
return false;
}
@Override
public boolean isShiftKeyDown() {
if (lastInputEvent != null) {
return lastInputEvent.isShiftDown();
}
return false;
}
@Override
public boolean isAltKeyDown() {
if (lastInputEvent != null) {
return lastInputEvent.isAltDown();
}
return false;
}
@Override
public boolean isAltGraphKeyDown() {
if (lastInputEvent != null) {
return lastInputEvent.isAltGraphDown();
}
return false;
}
@Override
public boolean isControlKeyDown() {
if (lastInputEvent != null) {
return lastInputEvent.isControlDown();
}
return false;
}
@Override
public boolean isMetaKeyDown() {
if (lastInputEvent != null) {
return lastInputEvent.isMetaDown();
}
return false;
}
private static void dumpSwingHierarchy(java.awt.Component root, String indent) {
System.out.println(indent + root.getName()+" "+root.getClass() + " "+root.getBounds());
if (root instanceof Container) {
Container rootc = (Container)root;
for (int i=0; i() {
@Override
public int compare(Method o1, Method o2) {
return methodPropertyName_(o1.getName()).toLowerCase().compareTo(methodPropertyName_(o2.getName()).toLowerCase());
}
});
System.out.println(indent + cmp.getClass().getName() + "{");
for (int i=0; i 5) {
// blit() has been called more than 5 times since last
// paintComponent() - we'll disable buffer thread safety
// to maximize performance.
blitCounter = 5;
if (bufferSafeMode) {
bufferSafeMode = false;
buffer = null;
}
} else if (blitCounter < 5) {
// blit() has not been called more than 5 times since
// last paintComponent() call - so we'll enable buffer
// thread safety.
if (!bufferSafeMode) {
bufferSafeMode = true;
synchronized(bufferLock) {
buffer = null;
updateBuffer(edtBuffer);
updateEdtBufferSize();
bufferUpdated = true;
}
//System.out.println("On");
}
}
if (bufferSafeMode) {
// When using buffer safe mode, we copy the edtBuffer
// to the buffer in a synchronized block so that
// there is no possible conflict when paintComponent()
// is called.
if (!bufferUpdated) {
synchronized (bufferLock) {
updateBuffer(edtBuffer);
updateEdtBufferSize();
}
}
} else {
// When not using buffer safe mode, we just use the same
// edt buffer from AWT
buffer = edtBuffer;
}
try {
Runnable r = new Runnable() {
public void run() {
if (buffer != null) {
java.awt.Graphics g = getGraphics();
if (g == null) {
return;
}
blitTx = ((Graphics2D)g).getTransform().getTranslateX();
blitTy = ((Graphics2D)g).getTransform().getTranslateY();
if (bufferSafeMode) {
// If AWT is painting and CN1 is painting
// then we need to be more careful. Safe mode
// is enabled whenever AWT starts painting - this
// generally only occurs when there is a native
// peer on the screen
synchronized(bufferLock) {
drawScreenBuffer(g);
}
} else {
drawScreenBuffer(g);
updateEdtBufferSize();
}
if (window != null) {
if (zoomLevel != 1) {
Graphics2D g2d = (Graphics2D) g;
g2d.setTransform(AffineTransform.getScaleInstance(1, 1));
}
if (window.getJMenuBar() != null) {
for (int i = 0; i < window.getJMenuBar().getComponentCount(); i++) {
JMenu m = (JMenu) window.getJMenuBar().getComponent(i);
if (m.isPopupMenuVisible()) {
JPopupMenu pop = m.getPopupMenu();
pop.getInvoker().getX();
g.translate(pop.getInvoker().getX(), 0);
pop.update(g);
g.translate(-pop.getInvoker().getX(), 0);
}
}
}
}
g.dispose();
}
}
};
if(isDesignMode()) {
SwingUtilities.invokeLater(r);
} else {
SwingUtilities.invokeAndWait(r);
}
} catch(Exception err) {
err.printStackTrace();
}
}
public void blit(int x, int y, int w, int h) {
blit();
}
@Override
protected void paintChildren(java.awt.Graphics g) {
}
private boolean drawScreenBuffer(java.awt.Graphics g) {
if (buffer == null) {
return false;
}
//g.setColor(Color.white);
//g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
AffineTransform t = ((Graphics2D)g).getTransform();
AffineTransform t2 = AffineTransform.getScaleInstance(1/retinaScale, 1/retinaScale);
t2.concatenate(t);
((Graphics2D)g).setTransform(t2);
boolean painted = false;
Rectangle screenCoord = getScreenCoordinates();
if (screenCoord != null) {
if(getComponentCount() > 0) {
Graphics2D bg = buffer.createGraphics();
if(zoomLevel != 1) {
AffineTransform af = bg.getTransform();
bg.setTransform(AffineTransform.getScaleInstance(1, 1));
bg.translate(-(screenCoord.x + x )* zoomLevel, -(screenCoord.y + y ) * zoomLevel);
super.paintChildren(bg);
bg.setTransform(af);
} else {
bg.translate(-screenCoord.x - x, -screenCoord.y - y);
super.paintChildren(bg);
}
bg.dispose();
painted = true;
}
if(roundedSkin) {
Graphics2D bg = buffer.createGraphics();
BufferedImage skin = getSkin();
bg.drawImage(skin, -(int) ((getScreenCoordinates().getX()) * zoomLevel), -(int) ((getScreenCoordinates().getY()) * zoomLevel),
(int)(skin.getWidth() * zoomLevel), (int)(skin.getHeight() * zoomLevel), null);
bg.dispose();
}
if (isEnabled()) {
g.drawImage(buffer, (int) ((getScreenCoordinates().getX() + x) * zoomLevel), (int) ((getScreenCoordinates().getY() + y) * zoomLevel), this);
} else {
g.setColor(Color.WHITE);
g.fillRect(x + (int) (getSkin().getWidth() * zoomLevel), y, getWidth(), getHeight());
g.fillRect(x, y + (int) (getSkin().getHeight() * zoomLevel), getWidth(), getHeight());
java.awt.Graphics g1 = buffer.getGraphics();
g1.setColor(Color.WHITE);
g1.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
g1.setColor(Color.BLACK);
java.awt.Font f = new java.awt.Font("Arial", Font.STYLE_BOLD, 20);
g1.setFont(f);
int sw = (int) Math.ceil(f.getStringBounds("Paused", canvas.getFRC()).getWidth());
g1.drawString("Paused", buffer.getWidth() / 2 - sw / 2, buffer.getHeight() / 2 - f.getSize() / 2);
g.drawImage(buffer, (int) ((getScreenCoordinates().getX() + x) * zoomLevel), (int) ((getScreenCoordinates().getY() + y) * zoomLevel), this);
}
//updateGraphicsScale(g);
BufferedImage skin = getSkin();
g.drawImage(skin, (int) (x * zoomLevel), (int) (( y) * zoomLevel),
(int)(skin.getWidth() * zoomLevel), (int)(skin.getHeight() * zoomLevel), null);
if (zoomLevel != 1) {
AffineTransform t3 = ((Graphics2D)g).getTransform();
t3.scale(zoomLevel/t3.getScaleX()/retinaScale, zoomLevel/t3.getScaleX()/retinaScale);
//AffineTransform t3 = AffineTransform.getScaleInstance(zoomLevel, zoomLevel);
((Graphics2D)g).setTransform(t3);
}
//((Graphics2D)g).setTransform(t2);
/*
g.drawImage(getSkin(),
(int)(x * retinaScale),
(int)(y * retinaScale),
(int)(getSkin().getWidth() * retinaScale),
(int)(getSkin().getHeight() * retinaScale), this);
*/
} else {
if(getComponentCount() > 0) {
Graphics2D bg = buffer.createGraphics();
if(zoomLevel != 1) {
AffineTransform af = bg.getTransform();
bg.setTransform(AffineTransform.getScaleInstance(1, 1));
super.paintChildren(bg);
bg.setTransform(af);
} else {
super.paintChildren(bg);
}
bg.dispose();
painted = true;
}
g.drawImage(buffer, x, y, this);
}
((Graphics2D)g).setTransform(t);
return painted;
}
private boolean bufferSafeMode;
public void paintComponent(java.awt.Graphics g) {
//if (true) return;
// This will turn on buffer safe mode
// next time blit() is run
blitCounter=0;
if (buffer != null) {
Graphics2D g2 = (Graphics2D)g.create();
AffineTransform t = g2.getTransform();
double tx = t.getTranslateX();
double ty = t.getTranslateY();
AffineTransform t2 = AffineTransform.getScaleInstance(retinaScale, retinaScale);
t2.translate(tx, ty);
if (getJavaVersion() < 9) {
// Java 8 didn't have full retina support
t2 = AffineTransform.getScaleInstance(1, 1);
t2.translate(tx * retinaScale, ty * retinaScale);
}
g2.setTransform(t2);
synchronized(bufferLock) {
drawScreenBuffer(g2);
}
g2.dispose();
//updateBufferSize();
if (Display.isInitialized()) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
Form f = getCurrentForm();
if (f != null) {
f.repaint();
}
}
});
}
} else {
Display.getInstance().callSerially(new Runnable() {
public void run() {
flushGraphics();
}
});
}
}
private void updateGraphicsScale(java.awt.Graphics g) {
if (zoomLevel != 1) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform t= g2d.getTransform();
//t.translate(-t.getTranslateX(), -t.getTranslateY());
t.scale(1/t.getScaleX(), 1/t.getScaleY());
//System.out.println("Updating graphics scale to "+zoomLevel);
t.scale(zoomLevel, zoomLevel);
g2d.setTransform(t);
}
}
public java.awt.Dimension getPreferredSize() {
if (forcedSize != null) {
return forcedSize;
}
if (getSkin() != null) {
return new java.awt.Dimension((int)(getSkin().getWidth() / retinaScale), (int)(getSkin().getHeight() / retinaScale));
}
Form f = Display.getInstance().getCurrent();
if (f != null) {
return new java.awt.Dimension((int)(f.getPreferredW() / retinaScale), (int)(f.getPreferredH() / retinaScale));
}
return new java.awt.Dimension(800, 480);
}
public FontRenderContext getFRC() {
return getGraphics2D().getFontRenderContext();
}
public Graphics2D getGraphics2D() {
updateEdtBufferSize();
while(g2dInstance == null) {
g2dInstance = edtBuffer.createGraphics();
updateGraphicsScale(g2dInstance);
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
}
}
return g2dInstance;
}
private BufferedImage createBufferedImage() {
g2dInstance = null;
if (getScreenCoordinates() != null) {
return new BufferedImage(Math.max(20, (int) (getScreenCoordinates().width * zoomLevel)), Math.max(20, (int) (getScreenCoordinates().height * zoomLevel)), BufferedImage.TYPE_INT_RGB);
}
return new BufferedImage(Math.max(20, (int)(getWidth() * retinaScale)), Math.max(20, (int)(getHeight() * retinaScale)), BufferedImage.TYPE_INT_RGB);
}
public void validate() {
super.validate();
//buffer = createBufferedImage();
Form current = getCurrentForm();
if (current == null) {
return;
}
}
private int getCode(java.awt.event.KeyEvent evt) {
int code = evt.getKeyCode();
switch (code) {
case KeyEvent.VK_UP:
return GAME_KEY_CODE_UP;
case KeyEvent.VK_DOWN:
return GAME_KEY_CODE_DOWN;
case KeyEvent.VK_LEFT:
return GAME_KEY_CODE_LEFT;
case KeyEvent.VK_RIGHT:
return GAME_KEY_CODE_RIGHT;
case KeyEvent.VK_SPACE:
case KeyEvent.VK_ENTER:
return GAME_KEY_CODE_FIRE;
}
char c = evt.getKeyChar();
if(c == java.awt.event.KeyEvent.CHAR_UNDEFINED) {
return evt.getKeyCode();
}
return c;
}
private int getCode(int k) {
switch (k) {
case KeyEvent.VK_UP:
return GAME_KEY_CODE_UP;
case KeyEvent.VK_DOWN:
return GAME_KEY_CODE_DOWN;
case KeyEvent.VK_LEFT:
return GAME_KEY_CODE_LEFT;
case KeyEvent.VK_RIGHT:
return GAME_KEY_CODE_RIGHT;
case KeyEvent.VK_SPACE:
case KeyEvent.VK_ENTER:
return GAME_KEY_CODE_FIRE;
}
return k;
}
public void keyTyped(KeyEvent e) {
}
// We only know if meta/ctrl/alt etc is down when the key is pressed, but we
// are taking action when the key is released... so we need to track whether the
// control key was down while a key was pressed.
private HashSet ignorePressedKeys = new HashSet();
public void keyPressed(KeyEvent e) {
if (!isEnabled()) {
return;
}
if (e.isMetaDown() && e.getKeyChar() == 'c') {
Form f = CN.getCurrentForm();
if (f != null) {
final TextSelection ts = f.getTextSelection();
if (ts.isEnabled()) {
CN.callSerially(new Runnable() {
public void run() {
final String text = ts.getSelectionAsText();
if (text != null && !text.trim().isEmpty()) {
EventQueue.invokeLater(new Runnable() {
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Clipboard clipboard = toolkit.getSystemClipboard();
StringSelection strSel = new StringSelection(text.trim());
clipboard.setContents(strSel, null);
}
});
}
}
});
}
}
}
if (e.isMetaDown() && e.getKeyChar() == 'a') {
Form f = CN.getCurrentForm();
if (f != null) {
final TextSelection ts = f.getTextSelection();
if (ts.isEnabled()) {
CN.callSerially(new Runnable() {
public void run() {
ts.selectAll();
}
});
}
}
}
lastInputEvent = e;
// block key combos that might generate unreadable events
if (e.isAltDown() || e.isControlDown() || e.isMetaDown() || e.isAltGraphDown()) {
ignorePressedKeys.add(e.getKeyCode());
return;
}
int code = getCode(e);
if (testRecorder != null) {
testRecorder.eventKeyPressed(code);
}
JavaSEPort.this.keyPressed(code);
}
public void keyReleased(KeyEvent e) {
boolean ignore = ignorePressedKeys.contains(e.getKeyCode());
if (ignore) ignorePressedKeys.remove(e.getKeyCode());
if (!isEnabled()) {
return;
}
lastInputEvent = e;
// block key combos that might generate unreadable events
if (ignore || e.isAltDown() || e.isControlDown() || e.isMetaDown() || e.isAltGraphDown()) {
return;
}
int code = getCode(e);
if (testRecorder != null) {
testRecorder.eventKeyReleased(code);
}
JavaSEPort.this.keyReleased(code);
}
public void mouseClicked(MouseEvent e) {
e.consume();
}
private boolean showContextMenu(final MouseEvent me) {
if (componentTreeInspector == null || !componentTreeInspector.isSimulatorRightClickEnabled()) return false;
JPopupMenu menu = new JPopupMenu();
registerMenuWithBlit(menu);
JMenuItem inspectElement = new JMenuItem("Inspect Component");
inspectElement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (componentTreeInspector != null && componentTreeInspector.isSimulatorRightClickEnabled()) {
Form f = Display.getInstance().getCurrent();
if (f != null) {
int x = scaleCoordinateX(me.getX());
int y = scaleCoordinateY(me.getY());
Component cmp = f.getComponentAt(x, y);
componentTreeInspector.inspectComponent(cmp);
}
}
}
});
menu.add(inspectElement);
menu.show(me.getComponent(), me.getX(), me.getY());
return true;
}
private int scaleCoordinateX(int coordinate) {
if (getScreenCoordinates() != null) {
return (int) (retinaScale * coordinate / zoomLevel - (getScreenCoordinates().x + x));
}
return (int)(coordinate * retinaScale);
}
private int scaleCoordinateY(int coordinate) {
if (getScreenCoordinates() != null) {
return (int) (retinaScale * coordinate / zoomLevel - (getScreenCoordinates().y + y));
}
return (int)(coordinate * retinaScale);
}
Integer triggeredKeyCode;
private boolean mouseDown;
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
if (showContextMenu(e)) {
return;
}
}
this.mouseDown = true;
Form f = Display.getInstance().getCurrent();
if (f != null) {
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
Component cmp = f.getComponentAt(x, y);
if (!(cmp instanceof PeerComponent)) {
cn1GrabbedDrag = true;
}
}
e.consume();
if (!isEnabled()) {
return;
}
lastInputEvent = e;
if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 || (e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
releaseLock = false;
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
if (x >= 0 && x < getDisplayWidthImpl() && y >= 0 && y < getDisplayHeightImpl()) {
if (touchDevice) {
if (testRecorder != null) {
testRecorder.eventPointerPressed(x, y);
}
JavaSEPort.this.pointerPressed(x, y);
}
} else {
if (getSkin() != null) {
java.awt.Point p = new java.awt.Point((int) ((e.getX() - canvas.x) / zoomLevel), (int) ((e.getY() - canvas.y) / zoomLevel));
Integer keyCode;
keyCode = getSkinHotspots().get(p);
if (keyCode != null) {
if (rotateTouchKeysOnLandscape && !isPortrait()) {
// rotate touch keys on landscape mode
switch (keyCode) {
case KeyEvent.VK_UP:
keyCode = KeyEvent.VK_LEFT;
break;
case KeyEvent.VK_DOWN:
keyCode = KeyEvent.VK_RIGHT;
break;
case KeyEvent.VK_LEFT:
keyCode = KeyEvent.VK_DOWN;
break;
case KeyEvent.VK_RIGHT:
keyCode = KeyEvent.VK_UP;
break;
}
}
triggeredKeyCode = keyCode;
int code = getCode(keyCode.intValue());
if (testRecorder != null) {
testRecorder.eventKeyPressed(code);
}
JavaSEPort.this.keyPressed(code);
}
}
}
requestFocus();
}
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
if (showContextMenu(e)) {
return;
}
}
boolean mouseDown = this.mouseDown;
this.mouseDown = false;
cn1GrabbedDrag = false;
e.consume();
if (!isEnabled()) {
return;
}
lastInputEvent = e;
if ((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 || (e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
if (mouseDown || (x >= 0 && x < getDisplayWidthImpl() && y >= 0 && y < getDisplayHeightImpl())) {
if (touchDevice) {
x = Math.min(getDisplayWidthImpl(), Math.max(0, x));
y = Math.min(getDisplayHeightImpl(), Math.max(0, y));
if (testRecorder != null) {
testRecorder.eventPointerReleased(x, y);
}
JavaSEPort.this.pointerReleased(x, y);
}
}
if (triggeredKeyCode != null) {
int code = getCode(triggeredKeyCode.intValue());
if (testRecorder != null) {
testRecorder.eventKeyReleased(code);
}
JavaSEPort.this.keyReleased(code);
triggeredKeyCode = null;
}
}
}
public void mouseEntered(MouseEvent e) {
e.consume();
}
public void mouseExited(MouseEvent e) {
e.consume();
}
public void mouseDragged(MouseEvent e) {
e.consume();
if (!isEnabled()) {
return;
}
lastInputEvent = e;
if (!releaseLock && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
if (mouseDown || (x >= 0 && x < getDisplayWidthImpl() && y >= 0 && y < getDisplayHeightImpl())) {
if (touchDevice) {
x = Math.min(getDisplayWidthImpl(), Math.max(0, x));
y = Math.min(getDisplayHeightImpl(), Math.max(0, y));
if (testRecorder != null && hasDragStarted(x, y)) {
testRecorder.eventPointerDragged(x, y);
}
JavaSEPort.this.pointerDragged(x, y);
}
}
return;
}
// right click dragging means a pinch to zoom
if (!releaseLock && isPinchZoom(e)) {
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
if (mouseDown || (x >= 0 && x < getDisplayWidthImpl() && y >= 0 && y < getDisplayHeightImpl())) {
if (touchDevice) {
JavaSEPort.this.pointerDragged(new int[]{Math.min(getDisplayWidthImpl(), Math.max(0,x)), 0}, new int[]{Math.min(getDisplayHeightImpl(), Math.max(0, y)), 0});
}
}
return;
}
}
private boolean isPinchZoom(MouseEvent e) {
return ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0)
|| ((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0);
}
private Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
private Cursor defaultCursor = Cursor.getDefaultCursor();
private int currentCursor = 0;
private java.util.Timer reSize;
public void mouseMoved(MouseEvent e) {
e.consume();
if (!isEnabled()) {
return;
}
lastInputEvent = e;
if(invokePointerHover) {
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
if (x >= 0 && x < getDisplayWidthImpl() && y >= 0 && y < getDisplayHeightImpl()) {
JavaSEPort.this.pointerHover(x, y);
}
}
Form f = Display.getInstance().getCurrent();
if (f != null && f.isEnableCursors()) {
int x = scaleCoordinateX(e.getX());
int y = scaleCoordinateY(e.getY());
if (x >= 0 && x < getDisplayWidthImpl() && y >= 0 && y < getDisplayHeightImpl()) {
Component cmp = f.getComponentAt(x, y);
if (cmp != null) {
int cursor = cmp.getCursor();
if (cursor != currentCursor) {
currentCursor = cursor;
setCursor(Cursor.getPredefinedCursor(cursor));
}
} else {
if (currentCursor != 0) {
currentCursor = 0;
setCursor(defaultCursor);
}
}
} else {
if (currentCursor != 0) {
setCursor(defaultCursor);
}
}
} else {
if (currentCursor != 0) {
setCursor(defaultCursor);
}
}
if (getSkinHotspots() != null) {
java.awt.Point p = new java.awt.Point((int) ((e.getX() - canvas.x) / zoomLevel), (int) ((e.getY() - canvas.y) / zoomLevel));
if (getSkinHotspots().containsKey(p)) {
setCursor(handCursor);
} else {
setCursor(currentCursor == 0 ? defaultCursor : Cursor.getPredefinedCursor(currentCursor));
}
}
}
public void ancestorMoved(HierarchyEvent e) {
}
public void setBounds(int x, int y, int w, int h) {
super.setBounds(x, y, w, h);
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
boolean desktopSkin = pref.getBoolean("desktopSkin", false);
if (getSkin() == null && !desktopSkin) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
JavaSEPort.this.sizeChanged((int)(getWidth() * retinaScale), (int)(getHeight() * retinaScale));
}
});
}
}
public void ancestorResized(HierarchyEvent e) {
/*
if (e.getChanged() != getParent()) {
EventQueue.invokeLater(new Runnable() {
public void run() {
System.out.println("Parent size: "+getParent().getSize()+"; Window size "+((JFrame)getTopLevelAncestor()).getContentPane().getSize());
getParent().setSize(((JFrame)getTopLevelAncestor()).getContentPane().getSize());
}
});
return;
} */
if (getSkin() != null) {
if (!scrollableSkin) {
float w1 = ((float) getParent().getWidth() * (float)retinaScale) / ((float) getSkin().getWidth());
float h1 = ((float) getParent().getHeight() * (float)retinaScale) / ((float) getSkin().getHeight());
zoomLevel = Math.min(h1, w1);
Form f = Display.getInstance().getCurrent();
if (f != null) {
f.repaint();
}
}
getParent().repaint();
} else {
//some ugly hacks to workaround black screen issue
if (canvas != null && !fullScreen) {
//dumpSwingHierarchy(getTopLevelAncestor(), "");
Dimension topSize = ((JFrame)getTopLevelAncestor()).getContentPane().getSize();
Dimension parentSize = getParent().getSize();
if (e.getChanged() != getParent() && !topSize.equals(parentSize)) {
getParent().setSize(topSize);
getParent().doLayout();
}
setSize((int)topSize.getWidth(), (int)topSize.getHeight());
canvas.setForcedSize(new Dimension(getWidth(), getHeight()));
Display.getInstance().callSerially(new Runnable() {
public void run() {
JavaSEPort.this.sizeChanged((int)(getWidth() * retinaScale), (int)(getHeight() * retinaScale));
Form f = Display.getInstance().getCurrent();
if (f != null) {
f.revalidate();
}
}
});
return;
}
if(reSize == null){
reSize = new java.util.Timer();
}else{
reSize.cancel();
reSize = new java.util.Timer();
}
reSize.schedule(new TimerTask(){
@Override
public void run() {
//if(mediaContainer != null){
// System.out.println("Resize with media container");
// JavaSEPort.this.sizeChanged((int)(mediaContainer.getWidth() * retinaScale), (int)(mediaContainer.getHeight() * retinaScale));
//}else{
Display.getInstance().callSerially(new Runnable() {
public void run() {
JavaSEPort.this.sizeChanged((int)(getWidth() * retinaScale), (int)(getHeight() * retinaScale));
g2dInstance = null;
Form f = Display.getInstance().getCurrent();
if (f != null) {
f.forceRevalidate();
}
// probably not necessary
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1500);
} catch (Exception e) {
}
if (window != null) {
window.repaint();
}
}
}).start();
reSize = null;
}
});
//}
}
}, 200);
}
}
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
JScrollBar s = (JScrollBar) e.getSource();
int val = s.getValue();
if(getSkin() != null) {
if (s.getOrientation() == Scrollbar.HORIZONTAL) {
x = -(int) ((float) (val / 100f) * getSkin().getWidth());
} else {
y = -(int) ((float) (val / 100f) * getSkin().getHeight());
}
} else {
if (s.getOrientation() == Scrollbar.HORIZONTAL) {
x = -(int) ((float) (val / 100f) * getWidth());
} else {
y = -(int) ((float) (val / 100f) * getHeight());
}
}
repaint();
}
int lastUnits = 0;
boolean ignoreWheelMovements = false;
int lastX;
int lastY;
public void mouseWheelMoved(final MouseWheelEvent e) {
e.consume();
if (!isEnabled()) {
return;
}
lastInputEvent = e;
final int x = scrollWheeling ? lastX : scaleCoordinateX(e.getX());
final int y = scrollWheeling ? lastY : scaleCoordinateY(e.getY());
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
Form f = getCurrentForm();
if(f != null){
Component cmp;
try {
cmp = f.getComponentAt(x, y);
} catch (Throwable t) {
// Since this is called off the edt, we sometimes hit
// NPEs and Array Index out of bounds errors here
cmp = null;
}
if(cmp != null && Accessor.isScrollDecelerationMotionInProgress(cmp)) {
if (!ignoreWheelMovements) {
ignoreWheelMovements = true;
}
return;
} else {
ignoreWheelMovements = false;
}
}
requestFocus();
final int units = convertToPixels(e.getUnitsToScroll() * 5, true) * -1;
if (units * lastUnits < 0 || Math.abs(units) - Math.abs(lastUnits) > 100) {
ignoreWheelMovements = false;
}
lastUnits = units;
lastX = x;
lastY = y;
if (ignoreWheelMovements) {
return;
}
Display.getInstance().callSerially(new Runnable() {
public void run() {
scrollWheeling = true;
Form f = getCurrentForm();
if(f != null){
Component cmp = f.getComponentAt(x, y);
if(cmp != null && cmp.isFocusable()) {
cmp.setFocusable(false);
f.pointerPressed(x, y);
f.pointerDragged(x, y + units / 4);
cmp.setFocusable(true);
} else {
f.pointerPressed(x, y);
f.pointerDragged(x, y + units / 4);
}
}
}
});
Display.getInstance().callSerially(new Runnable() {
public void run() {
Form f = getCurrentForm();
if(f != null){
Component cmp = f.getComponentAt(x, y);
if (cmp != null && Accessor.isScrollDecelerationMotionInProgress(cmp)) {
return;
}
if(cmp != null && cmp.isFocusable()) {
cmp.setFocusable(false);
f.pointerDragged(x, y + units / 4 * 2);
cmp.setFocusable(true);
} else {
f.pointerDragged(x, y + units / 4 * 2);
}
}
}
});
Display.getInstance().callSerially(new Runnable() {
public void run() {
Form f = getCurrentForm();
if(f != null){
Component cmp = f.getComponentAt(x, y);
if (cmp != null && Accessor.isScrollDecelerationMotionInProgress(cmp)) {
return;
}
if(cmp != null && cmp.isFocusable()) {
cmp.setFocusable(false);
f.pointerDragged(x, y + units / 4 * 3);
cmp.setFocusable(true);
} else {
f.pointerDragged(x, y + units / 4 * 3);
}
}
}
});
Display.getInstance().callSerially(new Runnable() {
public void run() {
Form f = getCurrentForm();
if(f != null){
Component cmp = f.getComponentAt(x, y);
if (cmp != null && Accessor.isScrollDecelerationMotionInProgress(cmp)) {
f.pointerReleased(x, y + units);
return;
}
if(cmp != null && cmp.isFocusable()) {
cmp.setFocusable(false);
f.pointerDragged(x, y + units);
f.pointerReleased(x, y + units);
cmp.setFocusable(true);
} else {
f.pointerDragged(x, y + units);
f.pointerReleased(x, y + units);
}
}
scrollWheeling = false;
}
});
}
}
}
protected boolean cn1GrabbedDrag=false;
public C canvas;
public java.awt.Container getCanvas() {
return canvas;
}
public static JavaSEPort instance;
public JavaSEPort() {
canvas = new C();
instance = this;
}
public void paintDirty() {
super.paintDirty();
}
/**
* @inheritDoc
*/
public void deinitialize() {
if (canvas.getParent() != null) {
canvas.getParent().remove(canvas);
}
}
/**
* Subclasses of this implementation might override this to return builtin
* skins for a specific implementation
*
* @return true if skins are used
*/
public boolean hasSkins() {
return System.getProperty("skin") != null || System.getProperty("dskin") != null;
}
private void initializeCoordinates(BufferedImage map, Properties props, Map coordinates, java.awt.Rectangle screenPosition) {
int[] buffer = new int[map.getWidth() * map.getHeight()];
map.getRGB(0, 0, map.getWidth(), map.getHeight(), buffer, 0, map.getWidth());
int screenX1 = Integer.MAX_VALUE;
int screenY1 = Integer.MAX_VALUE;
int screenX2 = 0;
int screenY2 = 0;
for (int iter = 0; iter < buffer.length; iter++) {
int pixel = buffer[iter];
// white pixels are blank
if (pixel != 0xffffffff) {
int x = iter % map.getWidth();
int y = iter / map.getWidth();
// black pixels represent the screen region
if (pixel == 0xff000000) {
if (x < screenX1) {
screenX1 = x;
}
if (y < screenY1) {
screenY1 = y;
}
if (x > screenX2) {
screenX2 = x;
}
if (y > screenY2) {
screenY2 = y;
}
} else {
String prop = "c" + Integer.toHexString(0xffffff & pixel);
String val = props.getProperty(prop);
int code = 0;
if (val == null) {
val = props.getProperty("x" + Integer.toHexString(pixel));
if (val == null) {
continue;
}
code = Integer.parseInt(val, 16);
} else {
code = Integer.parseInt(val);
}
coordinates.put(new Point(x, y), code);
}
}
}
double scale = 1.0; // retinaScale
screenPosition.x = (int)(screenX1 / scale);
screenPosition.y = (int)(screenY1 / scale);
screenPosition.width = (int)((screenX2 - screenX1 + 1)/scale);
screenPosition.height = (int)((screenY2 - screenY1 + 1)/scale);
}
private static void readFully(InputStream i, byte b[]) throws IOException {
readFully(i, b, 0, b.length);
}
private static final void readFully(InputStream i, byte b[], int off, int len) throws IOException {
if (len < 0) {
throw new IndexOutOfBoundsException();
}
int n = 0;
while (n < len) {
int count = i.read(b, off + n, len - n);
if (count < 0) {
throw new EOFException();
}
n += count;
}
}
@Override
public boolean isMinimized() {
if (Display.getInstance().isSimulator()) {
return minimized;
} else {
return super.isMinimized();
}
}
private void loadSkinFile(InputStream skin, final JFrame frm) {
try {
ZipInputStream z = new ZipInputStream(skin);
ZipEntry e = z.getNextEntry();
final Properties props = new Properties();
BufferedImage map = null;
BufferedImage landscapeMap = null;
// if we load the native theme imediately the multi-image's will be loaded with the size of the old skin
byte[] nativeThemeData = null;
nativeThemeRes = null;
nativeTheme = null;
while (e != null) {
String name = e.getName();
if (name.equals("skin.png")) {
portraitSkin = ImageIO.read(z);
e = z.getNextEntry();
continue;
}
if (name.equals("header.png")) {
header = ImageIO.read(z);
e = z.getNextEntry();
continue;
}
if (name.equals("header_l.png")) {
headerLandscape = ImageIO.read(z);
e = z.getNextEntry();
continue;
}
if (name.equals("skin.properties")) {
props.load(z);
e = z.getNextEntry();
continue;
}
if (name.equals("skin_l.png")) {
landscapeSkin = ImageIO.read(z);
e = z.getNextEntry();
continue;
}
if (name.equals("skin_map.png")) {
map = ImageIO.read(z);
e = z.getNextEntry();
continue;
}
if (name.equals("skin_map_l.png")) {
landscapeMap = ImageIO.read(z);
e = z.getNextEntry();
continue;
}
if (name.endsWith(".res")) {
long esize = e.getSize();
if(esize > 0) {
nativeThemeData = new byte[(int) esize];
readFully(z, nativeThemeData);
} else {
ByteArrayOutputStream b = new ByteArrayOutputStream();
Util.copyNoClose(z, b, 8192);
nativeThemeData = b.toByteArray();
}
e = z.getNextEntry();
continue;
}
if (name.endsWith(".ttf")) {
try {
java.awt.Font result = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT, z);
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(result);
} catch (FontFormatException ex) {
ex.printStackTrace();
} catch (IOException ex) {
if (ex.getMessage().contains("Problem reading font data")) {
System.err.println("Problem reading entry "+name+" from skin file");
System.err.println("This issue may be related to https://github.com/codenameone/CodenameOne/issues/2640");
System.err.println("The application should still function normally, although this font may not render correctly.");
System.err.println("Please help us out by posting your build output log to https://github.com/codenameone/CodenameOne/issues/2640 and any other information you think may be helpful in tracking down the cause.");
System.err.println("Skin Properties:");
System.err.println(props);
System.err.println("Stack Trace:");
ex.printStackTrace(System.err);
} else {
throw ex;
}
}
e = z.getNextEntry();
continue;
}
e = z.getNextEntry();
}
z.close();
String ppi = props.getProperty("ppi");
if(ppi != null) {
double ppiD = Double.valueOf(ppi);
pixelMilliRatio = ppiD / 25.4;
} else {
String pix = props.getProperty("pixelRatio");
if (pix != null && pix.length() > 0) {
try {
pixelMilliRatio = Double.valueOf(pix);
} catch (NumberFormatException err) {
err.printStackTrace();
pixelMilliRatio = null;
}
} else {
pixelMilliRatio = null;
}
}
portraitSkinHotspots = new HashMap();
portraitScreenCoordinates = new Rectangle();
landscapeSkinHotspots = new HashMap();
landscapeScreenCoordinates = new Rectangle();
if(props.getProperty("roundScreen", "false").equalsIgnoreCase("true")) {
safeAreaLandscape = new Rectangle();
safeAreaPortrait = new Rectangle();
portraitScreenCoordinates.x = Integer.parseInt(props.getProperty("displayX"));
portraitScreenCoordinates.y = Integer.parseInt(props.getProperty("displayY"));
portraitScreenCoordinates.width = Integer.parseInt(props.getProperty("displayWidth"));
portraitScreenCoordinates.height = Integer.parseInt(props.getProperty("displayHeight"));
landscapeScreenCoordinates.x = portraitScreenCoordinates.y;
landscapeScreenCoordinates.y = portraitScreenCoordinates.x;
landscapeScreenCoordinates.width = portraitScreenCoordinates.height;
landscapeScreenCoordinates.height = portraitScreenCoordinates.width;
safeAreaPortrait.setBounds(
Integer.parseInt(props.getProperty("safePortraitX", "0")),
Integer.parseInt(props.getProperty("safePortraitY", "0")),
Integer.parseInt(props.getProperty("safePortraitWidth", ""+portraitScreenCoordinates.width)),
Integer.parseInt(props.getProperty("safePortraitHeight", ""+portraitScreenCoordinates.height))
);
safeAreaLandscape.setBounds(
Integer.parseInt(props.getProperty("safeLandscapeX", "0")),
Integer.parseInt(props.getProperty("safeLandscapeY", "0")),
Integer.parseInt(props.getProperty("safeLandscapeWidth", ""+landscapeScreenCoordinates.width)),
Integer.parseInt(props.getProperty("safeLandscapeHeight", ""+landscapeScreenCoordinates.height))
);
roundedSkin = true;
} else {
initializeCoordinates(map, props, portraitSkinHotspots, portraitScreenCoordinates);
initializeCoordinates(landscapeMap, props, landscapeSkinHotspots, landscapeScreenCoordinates);
}
platformName = props.getProperty("platformName", "se");
platformOverrides = props.getProperty("overrideNames", "").split(",");
String ua = null;
if (platformName.equals("and")) {
ua = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
} else if (platformName.equals("rim")) {
ua = "Mozilla/5.0 (BlackBerry; U; BlackBerry 9860; en-GB) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.296 Mobile Safari/534.11+";
} else if (platformName.equals("ios")) {
if (isTablet()) {
ua = "Mozilla/5.0 (iPad; U; CPU OS 4_3_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4 Safari/6533.18.5";
} else {
ua = "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5";
}
} else if (platformName.equals("me")) {
ua = "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124";
} else {
if (platformName.equals("win")) {
ua = "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 800)";
} else {
ua = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
}
}
Display.getInstance().setProperty("User-Agent", ua);
isIOS = props.getProperty("systemFontFamily", "Arial").toLowerCase().contains("helvetica");
setFontFaces(props.getProperty("systemFontFamily", "Arial"),
props.getProperty("proportionalFontFamily", "SansSerif"),
props.getProperty("monospaceFontFamily", "Monospaced"));
int med;
int sm;
int la;
if(pixelMilliRatio == null) {
float factor = ((float) getDisplayHeightImpl()) / 480.0f;
med = (int) (15.0f * factor);
sm = (int) (11.0f * factor);
la = (int) (19.0f * factor);
} else {
med = (int) Math.round(2.6 * pixelMilliRatio.doubleValue());
sm = (int) Math.round(2 * pixelMilliRatio.doubleValue());
la = (int) Math.round(3.3 * pixelMilliRatio.doubleValue());
}
setFontSize(Integer.parseInt(props.getProperty("mediumFontSize", "" + med)),
Integer.parseInt(props.getProperty("smallFontSize", "" + sm)),
Integer.parseInt(props.getProperty("largeFontSize", "" + la)));
tablet = props.getProperty("tablet", "false").equalsIgnoreCase("true");
rotateTouchKeysOnLandscape = props.getProperty("rotateKeys", "false").equalsIgnoreCase("true");
touchDevice = props.getProperty("touch", "true").equalsIgnoreCase("true");
keyboardType = Integer.parseInt(props.getProperty("keyboardType", "0"));
softkeyCount = Integer.parseInt(props.getProperty("softbuttonCount", "1"));
if (softkeyCount < 2) {
// patch the MenuBar class in case we change the softkey count in runtime we need
// the values of the static variables to be correct!
try {
Field f = com.codename1.ui.MenuBar.class.getDeclaredField("leftSK");
f.setAccessible(true);
f.setInt(null, KeyEvent.VK_F1);
f = com.codename1.ui.MenuBar.class.getDeclaredField("rightSK");
f.setAccessible(true);
f.setInt(null, KeyEvent.VK_F2);
} catch (Throwable t) {
t.printStackTrace();
}
}
final byte[] nativeThemeFinalData = nativeThemeData;
Display.getInstance().callSerially(new Runnable() {
public void run() {
if (nativeThemeFinalData != null) {
try {
nativeThemeRes = Resources.open(new ByteArrayInputStream(nativeThemeFinalData));
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
try {
boolean isJ2me = props.getProperty("platformName", "").equals("me");
String t = props.getProperty("nativeThemeAttribute", null);
if (t != null) {
Properties cnop = new Properties();
File cnopFile = new File(getCWD(), "codenameone_settings.properties");
if (cnopFile.exists()) {
cnop.load(new FileInputStream(cnopFile));
int themeConst = Integer.parseInt(cnop.getProperty("codename1.j2me.nativeThemeConst", "3"));
t = cnop.getProperty(t, null);
if (isJ2me && themeConst == 3 && t != null && new File(t).exists()) {
nativeThemeRes = Resources.open(new FileInputStream(t));
}
}
}
} catch (IOException ioErr) {
ioErr.printStackTrace();
}
}
}
});
installMenu(frm, false);
} catch (IOException err) {
err.printStackTrace();
}
}
@Override
public com.codename1.ui.geom.Rectangle getDisplaySafeArea(com.codename1.ui.geom.Rectangle rect) {
if (!isSimulator() || safeAreaPortrait == null || safeAreaLandscape == null) {
return super.getDisplaySafeArea(rect);
}
if (rect == null) {
rect = new com.codename1.ui.geom.Rectangle();
}
if (portrait) {
rect.setBounds((int)safeAreaPortrait.getX(), (int)safeAreaPortrait.getY(), (int)safeAreaPortrait.getWidth(), (int)safeAreaPortrait.getHeight());
} else {
rect.setBounds((int)safeAreaLandscape.getX(), (int)safeAreaLandscape.getY(), (int)safeAreaLandscape.getWidth(), (int)safeAreaLandscape.getHeight());
}
return rect;
}
private JMenuItem debugInChromeMenuItem;
public void setChromeDebugPort(int port) {
System.setProperty("cef.debugPort", ""+port);
if (debugInChromeMenuItem != null) {
EventQueue.invokeLater(new Runnable() {
public void run() {
debugInChromeMenuItem.setEnabled(true);
}
});
}
}
private static ImageIcon getZoomIcon(boolean scrollableSkinValue) {
if (scrollableSkinValue) {
return SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_zoom_in_black_24dp.png"), ICON_SIZE, ICON_SIZE);
} else {
return SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_zoom_out_black_24dp.png"), ICON_SIZE, ICON_SIZE);
}
}
/**
* Mutator for scrollable skin that will trigger a UI update on
* change.
* @param scrollableSkinValue
*/
private static void setScrollableSkin(boolean scrollableSkinValue) {
if (scrollableSkin != scrollableSkinValue) {
scrollableSkin = scrollableSkinValue;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("Scrollable", scrollableSkin);
instance.updateFrameUI();
}
}
private void setPortrait(boolean portraitValue) {
if (portrait != portraitValue) {
portrait = portraitValue;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("Portrait", portrait);
updateFrameUI();
}
}
private void updateFrameUI() {
if (instance.appFrame != null) {
if (EventQueue.isDispatchThread()) {
instance.appFrame.updateAppFrameUI();
} else {
EventQueue.invokeLater(new Runnable() {
public void run() {
instance.appFrame.updateAppFrameUI();
}
});
}
}
}
public class OpenJavadocsAction extends AbstractAction implements AppFrame.UpdatableUI {
public OpenJavadocsAction() {
super("", SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_help_center_black_24dp.png"), ICON_SIZE, ICON_SIZE));
putValue(SHORT_DESCRIPTION, "Open JavaDocs");
update();
}
@Override
public void actionPerformed(ActionEvent e) {
Component currentComponent = componentTreeInspector.getCurrentComponent();
if (currentComponent == null) return;
Class componentClass = currentComponent.getClass();
while (componentClass != null) {
File jarFile = locateJar(componentClass);
if (jarFile != null && jarFile.exists() && jarFile.getName().endsWith(".jar")) {
File javadocsJar = new File(jarFile.getParentFile(), jarFile.getName());
if (!javadocsJar.getName().endsWith("-javadoc.jar")) {
String jnameBase = javadocsJar.getName().substring(0, javadocsJar.getName().lastIndexOf(".jar"));
javadocsJar = new File(javadocsJar.getParentFile(), jnameBase+"-javadoc.jar");
}
if (javadocsJar.exists()) {
File extractedDir = extractJar(javadocsJar);
File htmlFile = new File(extractedDir, getJavadocPath(componentClass));
if (htmlFile.exists()) {
if (openHtmlFile(htmlFile)) {
return;
}
}
}
}
componentClass = componentClass.getSuperclass();
}
JOptionPane.showMessageDialog(window, "No javadocs found for this component.");
}
protected void update() {
}
private boolean openHtmlFile(File file) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(file.toURI());
return true;
} catch (Exception ex) {
return false;
}
}
return false;
}
private File locateJar(Class clazz) {
try {
String uri = clazz.getResource("/"+getClassPathPathWithUnixSlash(clazz)).toURI().toString();
if (uri.startsWith("jar:")) {
uri = uri.substring(4);
}
if (uri.contains("!")) {
uri = uri.substring(0, uri.indexOf("!"));
}
return new File(new URI(uri));
} catch (Exception ex) {
return null;
}
}
private File extractJar(File jarFile) {
File extractedDir = new File(jarFile.getParentFile(), jarFile.getName()+"-extracted");
if (extractedDir.exists()) {
return extractedDir;
}
extractedDir.mkdir();
ProcessBuilder pb = new ProcessBuilder(findJarToolPath(), "xf", jarFile.getAbsolutePath());
pb.directory(extractedDir);
try {
if (pb.start().waitFor() == 0) {
return extractedDir;
} else {
extractedDir.delete();
return null;
}
} catch (Exception ex) {
extractedDir.delete();
return null;
}
}
private String findJarToolPath() {
if (MavenUtils.isRunningInJDK()) {
File javac = MavenUtils.findJavac();
if (javac.exists()) {
File jar = new File(javac.getParentFile(), "jar");
if (!jar.exists()) {
jar = new File(javac.getParentFile(), "jar.exe");
}
if (jar.exists()) {
return jar.getAbsolutePath();
}
}
}
String javaHome = System.getProperty("java.home");
if (javaHome != null) {
File fJavaHome = new File(javaHome);
if (fJavaHome.exists()) {
File binDir = new File(fJavaHome, "bin");
File jar = new File(binDir, "jar");
if (jar.exists()) {
return jar.getAbsolutePath();
}
jar = new File(binDir, "jar.exe");
if (jar.exists()) {
return jar.getAbsolutePath();
}
}
}
return "jar";
}
private String getClassPathPathWithUnixSlash(Class cls) {
return cls.getName().replace(".", "/")+".class";
}
private String getJavadocPath(Class cls) {
return cls.getName().replace(".", File.separator) + ".html";
}
@Override
public void onUpdateAppFrameUI(AppFrame frame) {
}
}
public class ZoomAction extends AbstractAction implements AppFrame.UpdatableUI {
private final boolean scrollableSkinValue;
public ZoomAction(boolean scrollableSkinValue) {
super("", getZoomIcon(scrollableSkinValue));
this.scrollableSkinValue = scrollableSkinValue;
if (scrollableSkinValue) {
putValue(SHORT_DESCRIPTION, "Zoom in");
} else {
putValue(SHORT_DESCRIPTION, "Zoom out");
}
update();
}
protected void update() {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
if (pref.getBoolean("desktopSkin", false)) {
setEnabled(false);
return;
}
if (scrollableSkin == scrollableSkinValue) {
setEnabled(false);
} else {
setEnabled(true);
}
}
@Override
public void actionPerformed(ActionEvent e) {
JFrame frm = window;
setScrollableSkin(scrollableSkinValue);
if (scrollableSkin) {
if (appFrame == null) {
frm.add(java.awt.BorderLayout.SOUTH, hSelector);
frm.add(java.awt.BorderLayout.EAST, vSelector);
} else {
canvas.getParent().add(java.awt.BorderLayout.SOUTH, hSelector);
canvas.getParent().add(java.awt.BorderLayout.EAST, vSelector);
}
} else {
java.awt.Container selectorParent = hSelector.getParent();
if (selectorParent != null) {
selectorParent.remove(hSelector);
selectorParent.remove(vSelector);
}
}
Container parent = canvas.getParent();
parent.remove(canvas);
if (scrollableSkin) {
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() / retinaScale), (int)(getSkin().getHeight() / retinaScale)));
} else {
int screenH = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
int screenW = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
float zoomY = getSkin().getHeight() > screenH ? screenH/(float)getSkin().getHeight() : 1f;
float zoomX = getSkin().getWidth() > screenW ? screenW/(float)getSkin().getWidth() : 1f;
float zoom = Math.min(zoomX, zoomY);
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() * zoom), (int)(getSkin().getHeight() * zoom)));
if (window != null) {
if (appFrame == null) {
window.setSize(new java.awt.Dimension((int) (getSkin().getWidth() * zoom), (int) (getSkin().getHeight() * zoom)));
} else {
// THis is a hack to get it to repaint.
// Probably this is because a full refresh of the canvas
// is triggered by the ancestorResized event, but
// Can't figure out how to trigger it otherwise, we
// this ugly thing increases the decreases the window size by
// one pixel to trigger the refresh.
// Without this, the simulator canvas doesn't update
// until the window is resized.
java.awt.Container top = (parent instanceof JComponent) ?
((JComponent)parent).getTopLevelAncestor() :
window;
if (top == null) top = window;
int currW = top.getWidth();
int currH = top.getHeight();
top.setSize(new Dimension(currW+1, currH+1));
top.revalidate();
top.setSize(new Dimension(currW, currH));
top.revalidate();
}
}
}
parent.add(BorderLayout.CENTER, canvas);
canvas.x = 0;
canvas.y = 0;
zoomLevel = 1;
if (appFrame != null) {
appFrame.revalidate();
Display.getInstance().getCurrent().repaint();
appFrame.repaint();
parent.revalidate();
parent.revalidate();
canvas.repaint();
Timer timer = new Timer();
TimerTask tt = new TimerTask() {
@Override
public void run() {
EventQueue.invokeLater(new Runnable() {
public void run() {
canvas.revalidate();
canvas.repaint();
}
});
}
};
timer.schedule(tt, 100L);
} else {
frm.invalidate();
frm.pack();
Display.getInstance().getCurrent().repaint();
frm.repaint();
}
}
@Override
public void onUpdateAppFrameUI(AppFrame frame) {
update();
}
}
private static ImageIcon getRotateActionImageIcon(boolean portraitValue) {
if (portraitValue) {
return SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_stay_current_portrait_black_24dp.png"), ICON_SIZE, ICON_SIZE);
} else {
return SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_stay_current_landscape_black_24dp.png"), ICON_SIZE, ICON_SIZE);
}
}
public class ScreenshotSettingsAction extends AbstractAction implements CompanionMenuAction {
public ScreenshotSettingsAction() {
super("", SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_expand_more_black_24dp.png"), ICON_SIZE/2, ICON_SIZE/2));
putValue(SHORT_DESCRIPTION, "Screenshot settings");
}
@Override
public void actionPerformed(ActionEvent e) {
final Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
includeHeaderInScreenshot = pref.getBoolean("includeHeaderScreenshot", true);
final JCheckBoxMenuItem includeHeaderMenu = new JCheckBoxMenuItem("Screenshot StatusBar");
includeHeaderMenu.setToolTipText("Include status bar area in Screenshots");
includeHeaderMenu.setSelected(includeHeaderInScreenshot);
includeHeaderMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
includeHeaderInScreenshot = includeHeaderMenu.isSelected();
pref.putBoolean("includeHeaderScreenshot", includeHeaderInScreenshot);
}
});
includeSkinInScreenshot = pref.getBoolean("includeSkinInScreenshot", false);
final JCheckBoxMenuItem includeSkinMenu = new JCheckBoxMenuItem("Screenshot Skin");
includeSkinMenu.setToolTipText("Include skin in Screenshots");
includeSkinMenu.setSelected(includeSkinInScreenshot);
includeSkinMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
includeSkinInScreenshot = includeSkinMenu.isSelected();
pref.putBoolean("includeSkinInScreenshot", includeSkinInScreenshot);
}
});
JPopupMenu popupMenu = new JPopupMenu();
registerMenuWithBlit(popupMenu);
popupMenu.add(includeHeaderMenu);
popupMenu.add(includeSkinMenu);
if (e.getSource() instanceof java.awt.Component) {
java.awt.Component cmp = (java.awt.Component)e.getSource();
popupMenu.show(cmp, 0, cmp.getHeight());
}
}
}
public class ScreenshotAction extends AbstractAction {
public ScreenshotAction() {
super("", SwingUtils.getImageIcon(JavaSEPort.class.getResource("baseline_photo_camera_black_24dp.png"), ICON_SIZE, ICON_SIZE));
putValue(SHORT_DESCRIPTION, "Screenshot");
}
public void actionPerformedWithSkin(ActionEvent e) {
final float zoom = zoomLevel;
zoomLevel = 1;
final Form frm = Display.getInstance().getCurrent();
BufferedImage headerImageTmp;
if (isPortrait()) {
headerImageTmp = header;
} else {
headerImageTmp = headerLandscape;
}
if (!includeHeaderInScreenshot) {
headerImageTmp = null;
}
int headerHeightTmp = 0;
if (headerImageTmp != null) {
headerHeightTmp = headerImageTmp.getHeight();
}
final int headerHeight = headerHeightTmp;
final BufferedImage headerImage = headerImageTmp;
//gr.translate(0, statusBarHeight);
Display.getInstance().callSerially(new Runnable() {
public void run() {
final com.codename1.ui.Image img = com.codename1.ui.Image.createImage(frm.getWidth(), frm.getHeight());
com.codename1.ui.Graphics gr = img.getGraphics();
takingScreenshot = true;
screenshotActualZoomLevel = zoom;
try {
frm.paint(gr);
} finally {
takingScreenshot = false;
}
final int imageWidth = img.getWidth();
final int imageHeight = img.getHeight();
final int[] imageRGB = img.getRGB();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BufferedImage bi = new BufferedImage(frm.getWidth(), frm.getHeight() + headerHeight, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, headerHeight, imageWidth, imageHeight, imageRGB, 0, imageWidth);
BufferedImage skin = getSkin();
BufferedImage newSkin = new BufferedImage(skin.getWidth(), skin.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = newSkin.createGraphics();
g2d.drawImage(bi, getScreenCoordinates().x, getScreenCoordinates().y, null);
if (headerImage != null) {
g2d.drawImage(headerImage, getScreenCoordinates().x, getScreenCoordinates().y, null);
}
g2d.drawImage(skin, 0, 0, null);
g2d.dispose();
OutputStream out = null;
try {
out = new FileOutputStream(findScreenshotFile());
ImageIO.write(newSkin, "png", out);
out.close();
} catch (Throwable ex) {
ex.printStackTrace();
System.exit(1);
} finally {
zoomLevel = zoom;
try {
out.close();
} catch (Throwable ex) {
}
frm.repaint();
canvas.repaint();
}
}
});
}
});
}
public void actionPerformed(ActionEvent ae) {
boolean includeSkin = includeSkinInScreenshot;
if (includeSkin) {
actionPerformedWithSkin(ae);
return;
}
final float zoom = zoomLevel;
zoomLevel = 1;
final Form frm = Display.getInstance().getCurrent();
BufferedImage headerImageTmp;
if (isPortrait()) {
headerImageTmp = header;
} else {
headerImageTmp = headerLandscape;
}
if (!includeHeaderInScreenshot) {
headerImageTmp = null;
}
int headerHeightTmp = 0;
if (headerImageTmp != null) {
headerHeightTmp = headerImageTmp.getHeight();
}
final int headerHeight = headerHeightTmp;
final BufferedImage headerImage = headerImageTmp;
//gr.translate(0, statusBarHeight);
Display.getInstance().callSerially(new Runnable() {
public void run() {
final com.codename1.ui.Image img = com.codename1.ui.Image.createImage(frm.getWidth(), frm.getHeight());
com.codename1.ui.Graphics gr = img.getGraphics();
takingScreenshot = true;
screenshotActualZoomLevel = zoom;
try {
frm.paint(gr);
} finally {
takingScreenshot = false;
}
final int imageWidth = img.getWidth();
final int imageHeight = img.getHeight();
final int[] imageRGB = img.getRGB();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BufferedImage bi = new BufferedImage(frm.getWidth(), frm.getHeight() + headerHeight, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, headerHeight, imageWidth, imageHeight, imageRGB, 0, imageWidth);
if (headerImage != null) {
Graphics2D g2d = bi.createGraphics();
g2d.drawImage(headerImage, 0, 0, null);
g2d.dispose();
}
OutputStream out = null;
try {
out = new FileOutputStream(findScreenshotFile());
ImageIO.write(bi, "png", out);
out.close();
} catch (Throwable ex) {
ex.printStackTrace();
System.exit(1);
} finally {
zoomLevel = zoom;
try {
out.close();
} catch (Throwable ex) {
}
frm.repaint();
canvas.repaint();
}
}
});
}
});
}
}
public class RotateAction extends AbstractAction implements AppFrame.UpdatableUI, SelectableAction {
private boolean portraitValue;
public RotateAction(boolean portraitValue) {
super("", getRotateActionImageIcon(portraitValue));
this.portraitValue = portraitValue;
if (portraitValue) {
putValue(SHORT_DESCRIPTION, "Rotate to portrait mode");
} else {
putValue(SHORT_DESCRIPTION, "Rotate to landscape mode");
}
update();
}
private void update() {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
boolean desktopSkin = pref.getBoolean("desktopSkin", false);
setEnabled(!desktopSkin);
Boolean selected = (Boolean)getValue(SELECTED_KEY);
if (selected == null) {
selected = false;
}
if (selected != (portraitValue == portrait)) {
putValue(SELECTED_KEY, portraitValue == portrait);
}
}
@Override
public void actionPerformed(ActionEvent e) {
setPortrait(portraitValue);
Container parent = canvas.getParent();
parent.remove(canvas);
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth()*zoomLevel), (int)(getSkin().getHeight()*zoomLevel)));
if (appFrame == null) {
if (window != null) {
window.setSize(new java.awt.Dimension((int) (getSkin().getWidth() * zoomLevel), (int) (getSkin().getHeight() * zoomLevel)));
}
}
java.awt.Container top = ((JComponent)parent).getTopLevelAncestor();
top.revalidate();
top.repaint();
parent.add(BorderLayout.CENTER, canvas);
if (appFrame == null) {
window.pack();
}
//zoomLevel = 1;
JavaSEPort.this.sizeChanged(getScreenCoordinates().width, getScreenCoordinates().height);
}
@Override
public void onUpdateAppFrameUI(AppFrame frame) {
update();
}
}
public void registerSplitPaneWithBlit(JSplitPane splitPane) {
SplitPaneUI spui = splitPane.getUI();
if (spui instanceof BasicSplitPaneUI) {
// Setting a mouse listener directly on split pane does not work, because no events are being received.
((BasicSplitPaneUI) spui).getDivider().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
menuDisplayed = true;
}
@Override
public void mouseReleased(MouseEvent e) {
menuDisplayed = false;
}
});
}
}
public void registerMenuWithBlit(JPopupMenu menu) {
menu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
menuDisplayed = true;
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
menuDisplayed = false;
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
menuDisplayed = false;
}
});
}
/**
* The simulator blit() function tends to draw over menus, so this method will
* register a menu to disable blit while the menu is opened.
* @param menu
*/
public void registerMenuWithBlit(JMenu menu) {
menu.setDoubleBuffered(true);
menu.addMenuListener(new MenuListener(){
@Override
public void menuSelected(MenuEvent e) {
menuDisplayed = true;
}
@Override
public void menuCanceled(MenuEvent e) {
menuDisplayed = false;
}
@Override
public void menuDeselected(MenuEvent e) {
menuDisplayed = false;
}
});
}
private void installMenu(final JFrame frm, boolean desktopSkin) throws IOException{
final Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
JMenuBar bar = new JMenuBar();
frm.setJMenuBar(bar);
JMenu simulatorMenu = new JMenu("Simulator");
registerMenuWithBlit(simulatorMenu);
JMenu simulateMenu = new JMenu("Simulate");
registerMenuWithBlit(simulateMenu);
JMenu toolsMenu = new JMenu("Tools");
registerMenuWithBlit(toolsMenu);
JMenuItem buildHintEditor = new JMenuItem("Edit Build Hints...");
ActionListener l = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new BuildHintEditor(JavaSEPort.this).show();
}
};
buildHintEditor.addActionListener(l);
toolsMenu.add(buildHintEditor);
final JCheckBoxMenuItem useAppFrameMenu = new JCheckBoxMenuItem("Single Window Mode", useAppFrame);
useAppFrameMenu.setToolTipText("Check this option to enable Single Window mode, in which the simulator, component inspector, network monitor and other tools are all included in a single, multi-panel window");
useAppFrameMenu.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
try {
pref.putBoolean("cn1.simulator.useAppFrame", useAppFrameMenu.isSelected());
deinitializeSync();
frm.dispose();
System.setProperty("reload.simulator", "true");
} catch (Exception ex) {
Log.e(ex);
}
}
});
simulatorMenu.add(useAppFrameMenu);
final JCheckBoxMenuItem zoomMenu = new JCheckBoxMenuItem("Zoom", scrollableSkin);
if (appFrame == null) simulatorMenu.add(zoomMenu);
JMenu debugEdtMenu = new JMenu("Debug EDT");
toolsMenu.add(debugEdtMenu);
zoomMenu.setEnabled(!desktopSkin);
JRadioButtonMenuItem debugEdtNone = new JRadioButtonMenuItem("None");
JRadioButtonMenuItem debugEdtLight = new JRadioButtonMenuItem("Light");
JRadioButtonMenuItem debugEdtFull = new JRadioButtonMenuItem("Full");
debugEdtMenu.add(debugEdtNone);
debugEdtMenu.add(debugEdtLight);
debugEdtMenu.add(debugEdtFull);
ButtonGroup bg = new ButtonGroup();
bg.add(debugEdtNone);
bg.add(debugEdtLight);
bg.add(debugEdtFull);
int debugEdtSelection = pref.getInt("debugEDTMode", 0);
switch (debugEdtSelection) {
case 0:
debugEdtNone.setSelected(true);
setShowEDTWarnings(false);
setShowEDTViolationStacks(false);
break;
case 2:
debugEdtFull.setSelected(true);
setShowEDTWarnings(true);
setShowEDTViolationStacks(true);
break;
default:
debugEdtLight.setSelected(true);
setShowEDTWarnings(true);
setShowEDTViolationStacks(false);
break;
}
debugEdtNone.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShowEDTWarnings(false);
setShowEDTViolationStacks(false);
pref.putInt("debugEDTMode", 0);
}
});
debugEdtFull.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShowEDTWarnings(true);
setShowEDTViolationStacks(true);
pref.putInt("debugEDTMode", 2);
}
});
debugEdtLight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShowEDTWarnings(true);
setShowEDTViolationStacks(false);
pref.putInt("debugEDTMode", 1);
}
});
JMenuItem screenshot = new JMenuItem("Screenshot");
if (appFrame == null) simulatorMenu.add(screenshot);
KeyStroke f2 = KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
screenshot.setAccelerator(f2);
screenshot.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
final float zoom = zoomLevel;
zoomLevel = 1;
final Form frm = Display.getInstance().getCurrent();
BufferedImage headerImageTmp;
if (isPortrait()) {
headerImageTmp = header;
} else {
headerImageTmp = headerLandscape;
}
if (!includeHeaderInScreenshot) {
headerImageTmp = null;
}
int headerHeightTmp = 0;
if (headerImageTmp != null) {
headerHeightTmp = headerImageTmp.getHeight();
}
final int headerHeight = headerHeightTmp;
final BufferedImage headerImage = headerImageTmp;
//gr.translate(0, statusBarHeight);
Display.getInstance().callSerially(new Runnable() {
public void run() {
final com.codename1.ui.Image img = com.codename1.ui.Image.createImage(frm.getWidth(), frm.getHeight());
com.codename1.ui.Graphics gr = img.getGraphics();
takingScreenshot = true;
screenshotActualZoomLevel = zoom;
try {
frm.paint(gr);
} finally {
takingScreenshot = false;
}
final int imageWidth = img.getWidth();
final int imageHeight = img.getHeight();
final int[] imageRGB = img.getRGB();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BufferedImage bi = new BufferedImage(frm.getWidth(), frm.getHeight() + headerHeight, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, headerHeight, imageWidth, imageHeight, imageRGB, 0, imageWidth);
if (headerImage != null) {
Graphics2D g2d = bi.createGraphics();
g2d.drawImage(headerImage, 0, 0, null);
g2d.dispose();
}
OutputStream out = null;
try {
out = new FileOutputStream(findScreenshotFile());
ImageIO.write(bi, "png", out);
out.close();
} catch (Throwable ex) {
ex.printStackTrace();
System.exit(1);
} finally {
zoomLevel = zoom;
try {
out.close();
} catch (Throwable ex) {
}
frm.repaint();
canvas.repaint();
}
}
});
}
});
}
});
JMenuItem screenshotWithSkin = new JMenuItem("Screenshot With Skin");
if (appFrame == null) simulatorMenu.add(screenshotWithSkin);
screenshotWithSkin.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final float zoom = zoomLevel;
zoomLevel = 1;
final Form frm = Display.getInstance().getCurrent();
BufferedImage headerImageTmp;
if (isPortrait()) {
headerImageTmp = header;
} else {
headerImageTmp = headerLandscape;
}
if (!includeHeaderInScreenshot) {
headerImageTmp = null;
}
int headerHeightTmp = 0;
if (headerImageTmp != null) {
headerHeightTmp = headerImageTmp.getHeight();
}
final int headerHeight = headerHeightTmp;
final BufferedImage headerImage = headerImageTmp;
//gr.translate(0, statusBarHeight);
Display.getInstance().callSerially(new Runnable() {
public void run() {
final com.codename1.ui.Image img = com.codename1.ui.Image.createImage(frm.getWidth(), frm.getHeight());
com.codename1.ui.Graphics gr = img.getGraphics();
takingScreenshot = true;
screenshotActualZoomLevel = zoom;
try {
frm.paint(gr);
} finally {
takingScreenshot = false;
}
final int imageWidth = img.getWidth();
final int imageHeight = img.getHeight();
final int[] imageRGB = img.getRGB();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BufferedImage bi = new BufferedImage(frm.getWidth(), frm.getHeight() + headerHeight, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, headerHeight, imageWidth, imageHeight, imageRGB, 0, imageWidth);
BufferedImage skin = getSkin();
BufferedImage newSkin = new BufferedImage(skin.getWidth(), skin.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = newSkin.createGraphics();
g2d.drawImage(bi, getScreenCoordinates().x, getScreenCoordinates().y, null);
if (headerImage != null) {
g2d.drawImage(headerImage, getScreenCoordinates().x, getScreenCoordinates().y, null);
}
g2d.drawImage(skin, 0, 0, null);
g2d.dispose();
OutputStream out = null;
try {
out = new FileOutputStream(findScreenshotFile());
ImageIO.write(newSkin, "png", out);
out.close();
} catch (Throwable ex) {
ex.printStackTrace();
System.exit(1);
} finally {
zoomLevel = zoom;
try {
out.close();
} catch (Throwable ex) {
}
frm.repaint();
canvas.repaint();
}
}
});
}
});
}
});
includeHeaderInScreenshot = pref.getBoolean("includeHeaderScreenshot", true);
final JCheckBoxMenuItem includeHeaderMenu = new JCheckBoxMenuItem("Screenshot StatusBar");
includeHeaderMenu.setToolTipText("Include status bar area in Screenshots");
includeHeaderMenu.setSelected(includeHeaderInScreenshot);
if (appFrame == null) simulatorMenu.add(includeHeaderMenu);
includeHeaderMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
includeHeaderInScreenshot = includeHeaderMenu.isSelected();
pref.putBoolean("includeHeaderScreenshot", includeHeaderInScreenshot);
}
});
JMenu networkDebug = new JMenu("Network");
toolsMenu.add(networkDebug);
JMenuItem networkMonitor = new JMenuItem("Network Monitor");
networkMonitor.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (netMonitor == null) {
showNetworkMonitor();
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("NetworkMonitor", true);
}
}
});
networkDebug.add(networkMonitor);
JMenuItem proxy = new JMenuItem("Proxy Settings");
proxy.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final JDialog proxy;
if(window !=null){
proxy = new JDialog(window);
}else{
proxy = new JDialog();
}
final Preferences pref = Preferences.userNodeForPackage(Component.class);
int proxySel = pref.getInt("proxySel", 2);
String proxySelHttp = pref.get("proxySel-http", "");
String proxySelPort = pref.get("proxySel-port", "");
JPanel panel = new JPanel();
panel.setAlignmentX( java.awt.Component.LEFT_ALIGNMENT );
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JPanel proxyUrl= new JPanel();
proxyUrl.setLayout(new FlowLayout(FlowLayout.LEFT));
proxyUrl.add(new JLabel("Http Proxy:"));
final JTextField http = new JTextField(proxySelHttp);
http.setColumns(20);
proxyUrl.add(http);
proxyUrl.add(new JLabel("Port:"));
final JTextField port = new JTextField(proxySelPort);
port.setColumns(4);
proxyUrl.add(port);
final JRadioButton noproxy = new JRadioButton("No Proxy");
JPanel rbPanel= new JPanel();
rbPanel.setLayout(new java.awt.GridLayout(1, 0));
rbPanel.setAlignmentX( java.awt.Component.LEFT_ALIGNMENT );
rbPanel.add(noproxy);
Dimension d = rbPanel.getPreferredSize();
d.width = proxyUrl.getPreferredSize().width;
rbPanel.setMinimumSize(d);
//noproxy.setPreferredSize(d);
panel.add(rbPanel);
final JRadioButton systemProxy = new JRadioButton("Use System Proxy");
rbPanel= new JPanel();
rbPanel.setLayout(new java.awt.GridLayout(1, 0));
rbPanel.setAlignmentX( java.awt.Component.LEFT_ALIGNMENT );
rbPanel.add(systemProxy);
d = rbPanel.getPreferredSize();
d.width = proxyUrl.getPreferredSize().width;
rbPanel.setPreferredSize(d);
panel.add(rbPanel);
final JRadioButton manual = new JRadioButton("Manual Proxy Settings:");
rbPanel= new JPanel();
rbPanel.setLayout(new java.awt.GridLayout(1, 0));
rbPanel.setAlignmentX( java.awt.Component.LEFT_ALIGNMENT );
rbPanel.add(manual);
d = rbPanel.getPreferredSize();
d.width = proxyUrl.getPreferredSize().width;
rbPanel.setPreferredSize(d);
panel.add(rbPanel);
rbPanel= new JPanel();
rbPanel.setLayout(new java.awt.GridLayout(1, 0));
rbPanel.setAlignmentX( java.awt.Component.LEFT_ALIGNMENT );
rbPanel.add(proxyUrl);
panel.add(rbPanel);
ButtonGroup group = new ButtonGroup();
group.add(noproxy);
group.add(systemProxy);
group.add(manual);
noproxy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
http.setEnabled(false);
port.setEnabled(false);
}
});
systemProxy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
http.setEnabled(false);
port.setEnabled(false);
}
});
manual.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
http.setEnabled(true);
port.setEnabled(true);
}
});
switch (proxySel){
case 1:
noproxy.setSelected(true);
http.setEnabled(false);
port.setEnabled(false);
break;
case 2:
systemProxy.setSelected(true);
http.setEnabled(false);
port.setEnabled(false);
break;
case 3:
manual.setSelected(true);
break;
}
JPanel closePanel = new JPanel();
JButton close = new JButton("Ok");
close.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (noproxy.isSelected()) {
pref.putInt("proxySel", 1);
} else if (systemProxy.isSelected()) {
pref.putInt("proxySel", 2);
} else if (manual.isSelected()) {
pref.putInt("proxySel", 3);
pref.put("proxySel-http", http.getText());
pref.put("proxySel-port", port.getText());
}
proxy.dispose();
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
if (perfMonitor != null) {
perfMonitor.dispose();
perfMonitor = null;
}
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
deinitializeSync();
frm.dispose();
System.setProperty("reload.simulator", "true");
} else {
refreshSkin(frm);
}
}
});
closePanel.add(close);
panel.add(closePanel);
proxy.add(panel);
proxy.pack();
if(window != null){
proxy.setLocationRelativeTo(window);
}
proxy.setResizable(false);
proxy.setVisible(true);
}
});
networkDebug.add(proxy);
networkDebug.addSeparator();
JRadioButtonMenuItem regularConnection = new JRadioButtonMenuItem("Regular Connection");
regularConnection.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
slowConnectionMode = false;
disconnectedMode = false;
pref.putInt("connectionStatus", 0);
}
});
networkDebug.add(regularConnection);
JRadioButtonMenuItem slowConnection = new JRadioButtonMenuItem("Slow Connection");
slowConnection.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
slowConnectionMode = true;
disconnectedMode = false;
pref.putInt("connectionStatus", 1);
}
});
networkDebug.add(slowConnection);
JRadioButtonMenuItem disconnected = new JRadioButtonMenuItem("Disconnected");
disconnected.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
slowConnectionMode = false;
disconnectedMode = true;
pref.putInt("connectionStatus", 2);
}
});
networkDebug.add(disconnected);
ButtonGroup connectionGroup = new ButtonGroup();
connectionGroup.add(regularConnection);
connectionGroup.add(slowConnection);
connectionGroup.add(disconnected);
switch(pref.getInt("connectionStatus", 0)) {
case 0:
regularConnection.setSelected(true);
break;
case 1:
slowConnection.setSelected(true);
slowConnectionMode = true;
break;
case 2:
disconnected.setSelected(true);
disconnectedMode = true;
break;
}
JMenuItem componentTreeInspector = new JMenuItem("Component Inspector");
componentTreeInspector.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (appFrame != null) return;
new ComponentTreeInspector().showInFrame();
}
});
JMenuItem scriptingConsole = new JMenuItem("Groovy Console");
scriptingConsole.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new CN1Console().open((java.awt.Component)e.getSource());
}
});
List inputArgs = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments();
//final boolean isDebug = inputArgs.toString().indexOf("-agentlib:jdwp") > 0;
//final boolean usingHotswapAgent = inputArgs.toString().indexOf("-XX:HotswapAgent") > 0;
ButtonGroup hotReloadGroup = new ButtonGroup();
JRadioButtonMenuItem disableHotReload = new JRadioButtonMenuItem("Disabled");
disableHotReload.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
pref.putInt("hotReload", 0);
System.setProperty("hotReload", "0");
}
});
JRadioButtonMenuItem reloadSimulator = new JRadioButtonMenuItem("Reload Simulator");
reloadSimulator.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
pref.putInt("hotReload", 1);
System.setProperty("hotReload", "1");
}
});
JRadioButtonMenuItem reloadCurrentForm = new JRadioButtonMenuItem("Reload Current Form (Requires CodeRAD)");
reloadCurrentForm.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
pref.putInt("hotReload", 2);
System.setProperty("hotReload", "2");
}
});
switch (pref.getInt("hotReload", 0)) {
case 0:
disableHotReload.setSelected(true);
System.setProperty("hotReload", "0");
break;
case 1:
reloadSimulator.setSelected(true);
System.setProperty("hotReload", "1");
break;
case 2:
reloadCurrentForm.setSelected(true);
System.setProperty("hotReload", "2");
break;
}
JMenu hotReloadMenu = new JMenu("Hot Reload");
hotReloadMenu.add(disableHotReload);
hotReloadMenu.add(reloadSimulator);
hotReloadMenu.add(reloadCurrentForm);
hotReloadGroup.add(disableHotReload);
hotReloadGroup.add(reloadSimulator);
hotReloadGroup.add(reloadCurrentForm);
if (isRunningInMaven() && MavenUtils.isRunningInJDK()) {
toolsMenu.add(hotReloadMenu);
}
scriptingConsole.setToolTipText("Open interactive console");
JMenuItem appArg = new JMenuItem("Send App Argument");
appArg.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Executor.stopApp();
JPanel pnl = new JPanel();
JTextField tf = new JTextField(20);
pnl.add(new JLabel("Argument to The App"));
pnl.add(tf);
int val = JOptionPane.showConfirmDialog(canvas, pnl, "Please Enter The Argument", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val != JOptionPane.OK_OPTION) {
Executor.startApp();
return;
}
String arg = tf.getText();
Display.getInstance().setProperty("AppArg", arg);
Executor.startApp();
}
});
simulateMenu.add(appArg);
JMenuItem debugWebViews = new JMenuItem("Debug Web Views");
debugWebViews.setEnabled(false);
debugInChromeMenuItem = debugWebViews;
debugWebViews.setToolTipText("Debug app's BrowserComponents' Javascript and DOM inside Chrome's debugger");
debugWebViews.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CN.callSerially(new Runnable() {
public void run() {
String port = System.getProperty("cef.debugPort", null);
if (port != null) {
final Sheet sheet = new Sheet(null, "Debug Web Views");
SpanLabel info = new SpanLabel("You can debug this app's web views in Chrome's "
+ "debugger by opening the following URL in Chrome:");
SpanLabel warning = new SpanLabel("Debugging only works in Chrome. If Chrome is not your default browser "
+ "then you'll need to copy and paste the URL above into Chrome");
ComponentSelector.select("*", warning).add(warning, true)
.selectAllStyles()
.setFontSizeMillimeters(2)
.setFgColor(0x555555);
FontImage.setMaterialIcon(warning, FontImage.MATERIAL_WARNING, 3);
final com.codename1.ui.TextField tf = new com.codename1.ui.TextField("http://localhost:"+port);
tf.addPointerPressedListener(new com.codename1.ui.events.ActionListener() {
@Override
public void actionPerformed(com.codename1.ui.events.ActionEvent evt) {
Display.getInstance().copyToClipboard(tf.getText());
ToastBar.showInfoMessage("URL Copied to Clipboard");
sheet.back();
}
});
tf.setEditable(false);
com.codename1.ui.Button copy = new com.codename1.ui.Button(com.codename1.ui.FontImage.MATERIAL_CONTENT_COPY);
copy.addActionListener(new com.codename1.ui.events.ActionListener() {
@Override
public void actionPerformed(com.codename1.ui.events.ActionEvent evt) {
Display.getInstance().copyToClipboard(tf.getText());
ToastBar.showInfoMessage("URL Copied to Clipboard");
sheet.back();
}
});
com.codename1.ui.Button open = new com.codename1.ui.Button("Open In Default Browser");
open.addActionListener(new com.codename1.ui.events.ActionListener() {
@Override
public void actionPerformed(com.codename1.ui.events.ActionEvent evt) {
CN.execute(tf.getText());
sheet.back();
}
});
sheet.getContentPane().setLayout(com.codename1.ui.layouts.BoxLayout.y());
sheet.getContentPane().add(info);
sheet.getContentPane().add(com.codename1.ui.layouts.BorderLayout.centerEastWest(tf, copy, null));
sheet.getContentPane().add(open);
sheet.getContentPane().add(warning);
sheet.setPosition(com.codename1.ui.layouts.BorderLayout.CENTER);
sheet.show();
} else {
ToastBar.showErrorMessage("Debugger not available. The Chrome debugger is only available in apps that contain a BrowserComponent");
}
}
});
}
});
toolsMenu.add(debugWebViews);
JMenuItem locationSim = new JMenuItem("Location Simulation");
locationSim.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if(locSimulation==null) {
locSimulation = new LocationSimulation();
}
locSimulation.setVisible(true);
}
});
simulateMenu.add(locationSim);
JMenuItem pushSim = new JMenuItem("Push Simulation");
pushSim.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if(pushSimulation == null) {
pushSimulation = new PushSimulator();
}
pref.putBoolean("PushSimulator", true);
pushSimulation.setVisible(true);
}
});
simulateMenu.add(pushSim);
if (appFrame == null) {
toolsMenu.add(componentTreeInspector);
}
toolsMenu.add(scriptingConsole);
JMenuItem testRecorderMenu = new JMenuItem("Test Recorder");
testRecorderMenu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (testRecorder == null) {
showTestRecorder();
}
}
});
toolsMenu.add(testRecorderMenu);
/*
JMenu darkLightModeMenu = new JMenu("Dark/Light Mode");
simulatorMenu.add(darkLightModeMenu);
final JRadioButtonMenuItem darkMode = new JRadioButtonMenuItem("Dark Mode");
final JRadioButtonMenuItem lightMode = new JRadioButtonMenuItem("Light Mode");
final JRadioButtonMenuItem unsupportedMode = new JRadioButtonMenuItem("Unsupported");
ButtonGroup group = new ButtonGroup();
group.add(darkMode);
group.add(lightMode);
group.add(unsupportedMode);
darkMode.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JavaSEPort.this.darkMode = true;
}
});
lightMode.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JavaSEPort.this.darkMode = false;
}
});
unsupportedMode.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JavaSEPort.this.darkMode = null;
}
});
*/
manualPurchaseSupported = pref.getBoolean("manualPurchaseSupported", true);
managedPurchaseSupported = pref.getBoolean("managedPurchaseSupported", true);
subscriptionSupported = pref.getBoolean("subscriptionSupported", true);
refundSupported = pref.getBoolean("refundSupported", true);
JMenu purchaseMenu = new JMenu("In App Purchase");
simulateMenu.add(purchaseMenu);
final JCheckBoxMenuItem manualPurchaseSupportedMenu = new JCheckBoxMenuItem("Manual Purchase");
manualPurchaseSupportedMenu.setSelected(manualPurchaseSupported);
final JCheckBoxMenuItem managedPurchaseSupportedMenu = new JCheckBoxMenuItem("Managed Purchase");
managedPurchaseSupportedMenu.setSelected(managedPurchaseSupported);
final JCheckBoxMenuItem subscriptionSupportedMenu = new JCheckBoxMenuItem("Subscription");
subscriptionSupportedMenu.setSelected(subscriptionSupported);
final JCheckBoxMenuItem refundSupportedMenu = new JCheckBoxMenuItem("Refunds");
refundSupportedMenu.setSelected(refundSupported);
manualPurchaseSupportedMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
manualPurchaseSupported = manualPurchaseSupportedMenu.isSelected();
pref.putBoolean("manualPurchaseSupported", manualPurchaseSupported);
}
});
managedPurchaseSupportedMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
managedPurchaseSupported = managedPurchaseSupportedMenu.isSelected();
pref.putBoolean("managedPurchaseSupported", managedPurchaseSupported);
}
});
subscriptionSupportedMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
subscriptionSupported = subscriptionSupportedMenu.isSelected();
pref.putBoolean("subscriptionSupported", subscriptionSupported);
}
});
refundSupportedMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
refundSupported = refundSupportedMenu.isSelected();
pref.putBoolean("refundSupported", refundSupported);
}
});
purchaseMenu.add(manualPurchaseSupportedMenu);
purchaseMenu.add(managedPurchaseSupportedMenu);
purchaseMenu.add(subscriptionSupportedMenu);
purchaseMenu.add(refundSupportedMenu);
JMenuItem performanceMonitor = new JMenuItem("Performance Monitor");
performanceMonitor.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (perfMonitor == null) {
showPerformanceMonitor();
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("PerformanceMonitor", true);
}
}
});
toolsMenu.add(performanceMonitor);
JMenuItem clean = new JMenuItem("Clean Storage");
clean.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
File home = new File(System.getProperty("user.home") + File.separator + appHomeDir);
if(!home.exists()){
return;
}
if(JOptionPane.showConfirmDialog(frm,
"Are you sure you want to Clean all Storage under "
+ home.getAbsolutePath() + " ?",
"Clean Storage",
JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION){
File [] files = home.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
file.delete();
}
}
}
});
toolsMenu.add(clean);
JMenu skinMenu = createSkinsMenu(frm, null);
skinMenu.addMenuListener(new MenuListener(){
@Override
public void menuSelected(MenuEvent e) {
menuDisplayed = true;
}
@Override
public void menuCanceled(MenuEvent e) {
menuDisplayed = false;
}
@Override
public void menuDeselected(MenuEvent e) {
menuDisplayed = false;
}
});
//final JCheckBoxMenuItem touchFlag = new JCheckBoxMenuItem("Touch", touchDevice);
//simulatorMenu.add(touchFlag);
//final JCheckBoxMenuItem nativeInputFlag = new JCheckBoxMenuItem("Native Input", useNativeInput);
//simulatorMenu.add(nativeInputFlag);
//final JCheckBoxMenuItem simulateAndroidVKBFlag = new JCheckBoxMenuItem("Simulate Android VKB", simulateAndroidKeyboard);
//simulatorMenu.add(simulateAndroidVKBFlag);
/*final JCheckBoxMenuItem slowMotionFlag = new JCheckBoxMenuItem("Slow Motion", false);
toolsMenu.add(slowMotionFlag);
slowMotionFlag.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Motion.setSlowMotion(slowMotionFlag.isSelected());
}
});*/
final JCheckBoxMenuItem permFlag = new JCheckBoxMenuItem("Android 6 Permissions", android6PermissionsFlag);
simulateMenu.add(permFlag);
permFlag.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
android6PermissionsFlag = !android6PermissionsFlag;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("Android6Permissions", android6PermissionsFlag);
}
});
pause = new JMenuItem("Pause App");
simulateMenu.addSeparator();
simulateMenu.add(pause);
pause.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (pause.getText().startsWith("Pause")) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
Executor.stopApp();
minimized = true;
}
});
canvas.setEnabled(false);
pause.setText("Resume App");
} else {
Display.getInstance().callSerially(new Runnable() {
public void run() {
Executor.startApp();
minimized = false;
}
});
canvas.setEnabled(true);
pause.setText("Pause App");
}
}
});
final JCheckBoxMenuItem alwaysOnTopFlag = new JCheckBoxMenuItem("Always on Top", alwaysOnTop);
if (appFrame == null) simulatorMenu.add(alwaysOnTopFlag);
if (appFrame == null) simulatorMenu.addSeparator();
JMenuItem exit = new JMenuItem("Exit");
simulatorMenu.add(exit);
JMenu helpMenu = new JMenu("Help");
helpMenu.setDoubleBuffered(true);
helpMenu.addMenuListener(new MenuListener(){
@Override
public void menuSelected(MenuEvent e) {
menuDisplayed = true;
}
@Override
public void menuCanceled(MenuEvent e) {
menuDisplayed = false;
}
@Override
public void menuDeselected(MenuEvent e) {
menuDisplayed = false;
}
});
JMenuItem javadocs = new JMenuItem("Javadocs");
javadocs.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
launchBrowserThatWorks("https://www.codenameone.com/javadoc/");
}
});
helpMenu.add(javadocs);
JMenuItem how = new JMenuItem("How Do I?...");
how.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
launchBrowserThatWorks("https://www.codenameone.com/how-do-i.html");
}
});
helpMenu.add(how);
JMenuItem forum = new JMenuItem("Community Forum");
forum.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
launchBrowserThatWorks("https://www.codenameone.com/discussion-forum.html");
}
});
helpMenu.add(forum);
JMenuItem bserver = new JMenuItem("Build Server");
bserver.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
launchBrowserThatWorks("https://cloud.codenameone.com/secure/index.html");
}
});
helpMenu.addSeparator();
helpMenu.add(bserver);
helpMenu.addSeparator();
JMenuItem about = new JMenuItem("About");
about.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final JDialog about;
if(window !=null){
about = new JDialog(window);
}else{
about = new JDialog();
}
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JPanel imagePanel = new JPanel();
JLabel image = new JLabel(new javax.swing.ImageIcon(getClass().getResource("/CodenameOne_Small.png")));
image.setHorizontalAlignment(SwingConstants.CENTER);
imagePanel.add(image);
panel.add(imagePanel);
JPanel linkPanel = new JPanel();
JButton link = new JButton();
link.setText("For more information, please
visit www.codenameone.com");
link.setHorizontalAlignment(SwingConstants.LEFT);
link.setBorderPainted(false);
link.setOpaque(false);
link.setBackground(Color.WHITE);
link.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
launchBrowserThatWorks("https://www.codenameone.com");
}
});
linkPanel.add(link);
panel.add(linkPanel);
JPanel closePanel = new JPanel();
JButton close = new JButton("close");
close.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
about.dispose();
}
});
closePanel.add(close);
panel.add(closePanel);
about.add(panel);
about.pack();
if(window != null){
about.setLocationRelativeTo(window);
}
about.setVisible(true);
}
});
helpMenu.add(about);
if (showMenu) {
bar.add(simulatorMenu);
bar.add(simulateMenu);
bar.add(toolsMenu);
bar.add(skinMenu);
bar.add(helpMenu);
}
alwaysOnTopFlag.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ie) {
alwaysOnTop = !alwaysOnTop;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("AlwaysOnTop", alwaysOnTop);
window.setAlwaysOnTop(alwaysOnTop);
}
});
ItemListener zoomListener = new ItemListener() {
public void itemStateChanged(ItemEvent ie) {
setScrollableSkin(!scrollableSkin);
if (scrollableSkin) {
if (appFrame == null) {
frm.add(java.awt.BorderLayout.SOUTH, hSelector);
frm.add(java.awt.BorderLayout.EAST, vSelector);
} else {
canvas.getParent().add(java.awt.BorderLayout.SOUTH, hSelector);
canvas.getParent().add(java.awt.BorderLayout.EAST, vSelector);
}
} else {
frm.remove(hSelector);
frm.remove(vSelector);
}
Container parent = canvas.getParent();
parent.remove(canvas);
if (scrollableSkin) {
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() / retinaScale), (int)(getSkin().getHeight() / retinaScale)));
} else {
int screenH = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
int screenW = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
float zoomY = getSkin().getHeight() > screenH ? screenH/(float)getSkin().getHeight() : 1f;
float zoomX = getSkin().getWidth() > screenW ? screenW/(float)getSkin().getWidth() : 1f;
float zoom = Math.min(zoomX, zoomY);
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() * zoom), (int)(getSkin().getHeight() * zoom)));
if (window != null) {
if (appFrame == null) {
window.setSize(new java.awt.Dimension((int) (getSkin().getWidth() * zoom), (int) (getSkin().getHeight() * zoom)));
}
}
}
parent.add(BorderLayout.CENTER, canvas);
canvas.x = 0;
canvas.y = 0;
zoomLevel = 1;
frm.invalidate();
frm.pack();
Display.getInstance().getCurrent().repaint();
frm.repaint();
}
};
zoomMenu.addItemListener(zoomListener);
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
exitApplication();
}
});
}
public static void resumeApp() {
Display.getInstance().callSerially(new Runnable() {
public void run() {
Executor.startApp();
instance.minimized = false;
}
});
instance.canvas.setEnabled(true);
pause.setText("Pause App");
}
File findScreenshotFile() {
int counter = 1;
File f = new File(System.getProperty("user.home"), "CodenameOne Screenshot " + counter + ".png");
while (f.exists()) {
counter++;
f = new File(System.getProperty("user.home"), "CodenameOne Screenshot " + counter + ".png");
}
return f;
}
private String getCurrentSkinName() {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
String skin = pref.get("skin", DEFAULT_SKIN);
while (skin.indexOf("/") >= 0) {
skin = skin.substring(skin.indexOf("/")+1);
}
while (skin.indexOf("\\") >= 0) {
skin = skin.substring(skin.indexOf("\\")+1);
}
return skin;
}
private JMenu createSkinsMenu(final JFrame frm, final JMenu menu) throws MalformedURLException {
JMenu m;
if (menu == null) {
m = new JMenu("Skins");
m.setDoubleBuffered(true);
} else {
m = menu;
m.removeAll();
}
final JMenu skinMenu = m;
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
String skinNames = pref.get("skins", DEFAULT_SKINS);
if (skinNames != null) {
if (skinNames.length() < DEFAULT_SKINS.length()) {
skinNames = DEFAULT_SKINS;
}
ButtonGroup skinGroup = new ButtonGroup();
StringTokenizer tkn = new StringTokenizer(skinNames, ";");
while (tkn.hasMoreTokens()) {
final String current = tkn.nextToken();
String name = current;
if (current.contains(":")) {
try {
URL u = new URL(current);
File f = new File(u.getFile());
if (!f.exists()) {
continue;
}
name = f.getName();
} catch (Exception e) {
continue;
}
} else {
// remove the old builtin skins from the menu
if(current.startsWith("/") && !current.equals(DEFAULT_SKIN)) {
continue;
}
}
String d = System.getProperty("dskin");
JRadioButtonMenuItem i = new JRadioButtonMenuItem(name, name.equals(pref.get("skin", d)));
i.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
if (perfMonitor != null) {
perfMonitor.dispose();
perfMonitor = null;
}
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("desktopSkin", false);
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
pref.put("skin", current);
frm.dispose();
System.setProperty("reload.simulator", "true");
} else {
loadSkinFile(current, frm);
refreshSkin(frm);
}
}
});
skinGroup.add(i);
skinMenu.add(i);
}
}
JMenuItem dSkin = new JMenuItem("Desktop.skin");
dSkin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
if (perfMonitor != null) {
perfMonitor.dispose();
perfMonitor = null;
}
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("desktopSkin", true);
pref.putBoolean("uwpDesktopSkin", false);
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
deinitializeSync();
frm.dispose();
System.setProperty("reload.simulator", "true");
}
}
});
JMenuItem uwpSkin = new JMenuItem("UWP Desktop.skin");
uwpSkin.setToolTipText("Windows 10 Desktop Skin");
uwpSkin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
if (perfMonitor != null) {
perfMonitor.dispose();
perfMonitor = null;
}
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.putBoolean("desktopSkin", true);
pref.putBoolean("uwpDesktopSkin", true);
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
deinitializeSync();
frm.dispose();
System.setProperty("reload.simulator", "true");
}
}
});
skinMenu.addSeparator();
skinMenu.add(dSkin);
skinMenu.add(uwpSkin);
skinMenu.addSeparator();
JMenuItem more = new JMenuItem("More...");
skinMenu.add(more);
more.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final JDialog pleaseWait = new JDialog(frm, false);
pleaseWait.setLocationRelativeTo(frm);
pleaseWait.setTitle("Message");
pleaseWait.setLayout(new BorderLayout());
pleaseWait.add(new JLabel(" Please Wait... "), BorderLayout.CENTER);
pleaseWait.pack();
pleaseWait.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JDialog d = new JDialog(frm, true);
d.setLocationRelativeTo(frm);
d.setTitle("Skins");
d.getContentPane().setLayout(new BorderLayout());
String userDir = System.getProperty("user.home");
final File skinDir = new File(userDir + "/.codenameone/");
if (!skinDir.exists()) {
skinDir.mkdir();
}
Vector data = new Vector();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
final Document[] doc = new Document[1];
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
InputStream is = openSkinsURL();
doc[0] = db.parse(is);
NodeList skins = doc[0].getElementsByTagName("Skin");
for (int i = 0; i < skins.getLength(); i++) {
Node skin = skins.item(i);
NamedNodeMap attr = skin.getAttributes();
String url = attr.getNamedItem("url").getNodeValue();
int ver = 0;
Node n = attr.getNamedItem("version");
if(n != null){
ver = Integer.parseInt(n.getNodeValue());
}
boolean exists = new File(skinDir.getAbsolutePath() + url).exists();
if (!(exists) || Integer.parseInt(pref.get(url, "0")) < ver) {
Vector row = new Vector();
row.add(new Boolean(false));
row.add(new ImageIcon(new URL(defaultCodenameOneComProtocol + "://www.codenameone.com/OTA" + attr.getNamedItem("icon").getNodeValue())));
row.add(attr.getNamedItem("name").getNodeValue());
if(exists){
row.add("Update");
}else{
row.add("New");
}
data.add(row);
}
}
} catch (Exception ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
}
if (data.size() == 0) {
pleaseWait.setVisible(false);
JOptionPane.showMessageDialog(frm, "No New Skins to Install");
return;
}
Vector cols = new Vector();
cols.add("Install");
cols.add("Icon");
cols.add("Name");
cols.add("");
final DefaultTableModel tableModel = new DefaultTableModel(data, cols) {
@Override
public boolean isCellEditable(int row, int column) {
return column == 0;
}
};
JTable skinsTable = new JTable(tableModel) {
@Override
public Class> getColumnClass(int column) {
if (column == 0) {
return Boolean.class;
}
if (column == 1) {
return Icon.class;
}
return super.getColumnClass(column);
}
};
skinsTable.setRowHeight(112);
skinsTable.getTableHeader().setReorderingAllowed(false);
final JTextField filter = new JTextField();
final TableRowSorter sorter = new TableRowSorter(((DefaultTableModel) skinsTable.getModel()));
filter.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() {
private void updateFilter() {
try {
RowFilter rf = RowFilter.regexFilter("(?i)"+filter.getText(),2);
sorter.setRowFilter(rf);
} catch (java.util.regex.PatternSyntaxException e) {
return;
}
}
@Override
public void insertUpdate(javax.swing.event.DocumentEvent e) {
updateFilter();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateFilter();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateFilter();
}
});
skinsTable.setRowSorter(sorter);
d.getContentPane().add(filter, BorderLayout.NORTH);
d.getContentPane().add(new JScrollPane(skinsTable), BorderLayout.CENTER);
JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton download = new JButton("Download");
download.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final Vector toDowload = new Vector();
NodeList skins = doc[0].getElementsByTagName("Skin");
for (int i = 0; i < tableModel.getRowCount(); i++) {
if (((Boolean) tableModel.getValueAt(i, 0)).booleanValue()) {
Node skin;
for (int j = 0; j < skins.getLength(); j++) {
skin = skins.item(j);
NamedNodeMap attr = skin.getAttributes();
if(attr.getNamedItem("name").getNodeValue().equals(tableModel.getValueAt(i, 2))){
String url = attr.getNamedItem("url").getNodeValue();
String [] data = new String[2];
data[0] = defaultCodenameOneComProtocol + "://www.codenameone.com/OTA" + url;
data[1] = attr.getNamedItem("version").getNodeValue();
toDowload.add(data);
break;
}
}
}
}
if (toDowload.size() > 0) {
final JDialog downloadMessage = new JDialog(d, true);
downloadMessage.setTitle("Downloading");
downloadMessage.setLayout(new FlowLayout());
downloadMessage.setLocationRelativeTo(d);
final JLabel details = new JLabel("
Details");
downloadMessage.add(details);
final JLabel progress = new JLabel("Progress
");
downloadMessage.add(progress);
new Thread() {
@Override
public void run() {
for (Iterator it = toDowload.iterator(); it.hasNext();) {
String [] data = (String []) it.next();
String url = data[0];
details.setText(url.substring(url.lastIndexOf("/")));
details.repaint();
progress.setText("");
progress.repaint();
try {
File skin = downloadSkin(skinDir, url, data[1], progress);
if (skin.exists()) {
addSkinName(skin.toURI().toString());
}
} catch (Exception e) {
}
}
downloadMessage.setVisible(false);
d.setVisible(false);
try {
createSkinsMenu(frm, skinMenu);
} catch (MalformedURLException ex) {
Logger.getLogger(JavaSEPort.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
downloadMessage.pack();
downloadMessage.setSize(200, 70);
downloadMessage.setVisible(true);
}else{
JOptionPane.showMessageDialog(d, "Choose a Skin to Download");
}
}
});
p.add(download);
d.getContentPane().add(p, BorderLayout.SOUTH);
d.pack();
pleaseWait.dispose();
d.setVisible(true);
}
});
}
});
skinMenu.addSeparator();
JMenuItem addSkin = new JMenuItem("Add New...");
skinMenu.add(addSkin);
addSkin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
FileDialog picker = new FileDialog(frm, "Add Skin");
picker.setMode(FileDialog.LOAD);
picker.setFilenameFilter(new FilenameFilter() {
public boolean accept(File file, String string) {
return string.endsWith(".skin");
}
});
picker.setModal(true);
picker.setVisible(true);
String file = picker.getFile();
if (file != null) {
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
if (perfMonitor != null) {
perfMonitor.dispose();
perfMonitor = null;
}
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.put("skin", picker.getDirectory() + File.separator + file);
deinitializeSync();
frm.dispose();
System.setProperty("reload.simulator", "true");
} else {
loadSkinFile(picker.getDirectory() + File.separator + file, frm);
refreshSkin(frm);
}
}
}
});
skinMenu.addSeparator();
JMenuItem reset = new JMenuItem("Reset Skins");
skinMenu.add(reset);
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(JOptionPane.showConfirmDialog(frm,
"Are you sure you want to reset skins to default?",
"Clean Storage",
JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION){
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.put("skins", DEFAULT_SKINS);
String userDir = System.getProperty("user.home");
final File skinDir = new File(userDir + "/.codenameone/");
if(skinDir.exists()){
File [] childs = skinDir.listFiles();
for (int i = 0; i < childs.length; i++) {
File child = childs[i];
if(child.getName().endsWith(".skin")){
child.delete();
}
}
}
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
if (perfMonitor != null) {
perfMonitor.dispose();
perfMonitor = null;
}
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
pref.put("skin", DEFAULT_SKIN);
deinitializeSync();
frm.dispose();
System.setProperty("reload.simulator", "true");
} else {
loadSkinFile(DEFAULT_SKIN, frm);
refreshSkin(frm);
}
}
}
});
return skinMenu;
}
InputStream openSkinsURL() throws IOException {
try {
URL u = new URL(defaultCodenameOneComProtocol + "://www.codenameone.com/OTA/Skins.xml");
HttpURLConnection uc = (HttpURLConnection)u.openConnection();
uc.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
InputStream is = uc.getInputStream();
return is;
} catch(IOException err) {
if(defaultCodenameOneComProtocol.equals("https")) {
defaultCodenameOneComProtocol = "http";
} else {
throw err;
}
System.out.println("Failed to connect thru secure socket, trying http instead");
URL u = new URL("http://www.codenameone.com/OTA/Skins.xml");
HttpURLConnection uc = (HttpURLConnection)u.openConnection();
uc.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
InputStream is = uc.getInputStream();
return is;
}
}
private void showTestRecorder() {
if (testRecorder == null) {
testRecorder = new TestRecorder();
testRecorder.pack();
testRecorder.setLocationByPlatform(true);
testRecorder.setVisible(true);
testRecorder.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
testRecorder = null;
}
});
}
}
private void showNetworkMonitor() {
if (netMonitor == null) {
netMonitor = new NetworkMonitor();
if (appFrame == null) {
netMonitor.showInNewWindow();
} else {
AppPanel existing = appFrame.getAppPanelById("NetworkMonitor");
if (existing == null) {
netMonitor = new NetworkMonitor();
existing = new AppPanel("NetworkMonitor", "Network Monitor", netMonitor);
existing.setPreferredFrame(AppFrame.FrameLocation.BottomPanel);
existing.setScrollable(false, true);
appFrame.add(existing);
}
}
}
}
private void showPerformanceMonitor() {
if (perfMonitor == null) {
perfMonitor = new PerformanceMonitor();
perfMonitor.pack();
perfMonitor.setLocationByPlatform(true);
perfMonitor.setVisible(true);
}
}
private void addSkinName(String f) {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
String skinNames = pref.get("skins", DEFAULT_SKINS);
if (skinNames != null) {
if (!skinNames.contains(f)) {
skinNames += ";" + f;
}
} else {
skinNames = f;
}
pref.put("skins", skinNames);
try {
pref.flush();
} catch(Throwable t) {
t.printStackTrace();
}
}
private void deepRevaliate(com.codename1.ui.Container c) {
c.setShouldCalcPreferredSize(true);
for (int iter = 0; iter < c.getComponentCount(); iter++) {
com.codename1.ui.Component cmp = c.getComponentAt(iter);
cmp.setShouldCalcPreferredSize(true);
if (cmp instanceof com.codename1.ui.Container) {
deepRevaliate((com.codename1.ui.Container) cmp);
}
}
}
private float zoomLevel() {
float w1 = ((float) canvas.getWidth() * (float)retinaScale) / ((float) getSkin().getWidth());
float h1 = ((float) canvas.getHeight() * (float)retinaScale) / ((float) getSkin().getHeight());
return Math.min(h1, w1);
}
private void refreshSkin(final JFrame frm) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
zoomLevel = zoomLevel();
Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_DEFAULT);
deepRevaliate(Display.getInstance().getCurrent());
if (hasNativeTheme()) {
Display.getInstance().installNativeTheme();
}
Display.getInstance().getCurrent().refreshTheme();
deepRevaliate(Display.getInstance().getCurrent());
JavaSEPort.this.sizeChanged(getScreenCoordinates().width, getScreenCoordinates().height);
Display.getInstance().getCurrent().revalidate();
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() * zoomLevel), (int)(getSkin().getHeight() * zoomLevel)));
zoomLevel = 1;
frm.pack();
}
});
}
private ArrayList deinitializeHooks = new ArrayList<>();
public void addDeinitializeHook(Runnable r) {
deinitializeHooks.add(r);
}
public void removeDeinitializeHook(Runnable r) {
deinitializeHooks.remove(r);
}
public void deinitializeSync() {
final Thread[] t = new Thread[1];
final boolean[] finished = new boolean[1];
Display.getInstance().callSeriallyAndWait(new Runnable() {
@Override
public void run() {
try {
t[0] = Thread.currentThread();
Form currForm = CN.getCurrentForm();
if (currForm != null) {
// Change to a dummy form to allow the current form to run its shutdown hooks.
Form dummy = new Form();
dummy.setTransitionInAnimator(null);
dummy.setTransitionOutAnimator(null);
currForm.setTransitionInAnimator(null);
currForm.setTransitionOutAnimator(null);
dummy.show();
}
ArrayList toDeinitialize = new ArrayList(deinitializeHooks);
deinitializeHooks.clear();
for (Runnable r : toDeinitialize) {
r.run();
}
} finally {
finished[0] = true;
}
}
}, 250);
Display.deinitialize();
if (netMonitor != null) {
netMonitor.dispose();
netMonitor = null;
}
NetworkManager.getInstance().shutdownSync();
try {
if (t[0] != null) {
long maxWait = 5000L;
long startTime = System.currentTimeMillis();
while (!finished[0] && (System.currentTimeMillis() - maxWait < startTime)) {
Thread.sleep(100);
}
//t[0].join();
}
} catch (Throwable ex) {
ex.printStackTrace();
}
}
private void loadSkinFile(String f, JFrame frm) {
try {
File fsFile = new File(f);
if (fsFile.exists()) {
f = fsFile.toURI().toString();
}
if (f.contains("://") || f.startsWith("file:")) {
try {
// load Via URL loading
loadSkinFile(new URL(f).openStream(), frm);
} catch (FileNotFoundException ex) {
String d = System.getProperty("dskin");
loadSkinFile(d, frm);
return;
} catch (MalformedURLException ex) {
loadSkinFile(getResourceAsStream(getClass(), DEFAULT_SKIN), frm);
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
InputStream is = getResourceAsStream(getClass(), f);
if(is != null) {
loadSkinFile(is, frm);
} else {
loadSkinFile(getResourceAsStream(getClass(), DEFAULT_SKIN), frm);
}
}
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.put("skin", f);
addSkinName(f);
} catch (Throwable t) {
System.out.println("Failed loading the skin file: " + f);
t.printStackTrace();
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.remove("skin");
}
}
/**
* @inheritDoc
*/
public void init(Object m) {
inInit = true;
/* File updater = new File(System.getProperty("user.home") + File.separator + ".codenameone" + File.separator + "UpdateCodenameOne.jar");
if(!updater.exists()) {
System.out.println("******************************************************************************");
System.out.println("* It seems that you are using an old plugin version please upate to the latest plugin and invoke Codename One -> Codename One Settings -> Basic -> Update Client Libs");
System.out.println("******************************************************************************");
}*/
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
boolean desktopSkin = pref.getBoolean("desktopSkin", false);
if (desktopSkin && m == null) {
safeAreaLandscape = null;
safeAreaPortrait = null;
Toolkit tk = Toolkit.getDefaultToolkit();
setDefaultPixelMilliRatio(tk.getScreenResolution() / 25.4 * getRetinaScale());
pixelMilliRatio = getDefaultPixelMilliRatio();
JPanel panel = new javax.swing.JPanel();
panel.setLayout(new BorderLayout());
JPanel bottom = new javax.swing.JPanel();
panel.setOpaque(false);
bottom.setLayout(new FlowLayout(FlowLayout.RIGHT));
widthLabel = new JLabel("Width: ");
heightLabel = new JLabel(" Height: ");
bottom.add(widthLabel);
bottom.add(heightLabel);
panel.add(bottom, BorderLayout.SOUTH);
JFrame frame = new JFrame();
//frame.addWindowListener(new WindowListener() {
//
//});
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.CENTER);
frame.setSize(new Dimension(300, 400));
m = panel;
window = frame;
if (pref.getBoolean("uwpDesktopSkin", false)) {
setNativeTheme("/winTheme.res");
} else {
setNativeTheme("/iOS7Theme.res");
}
}
setInvokePointerHover(desktopSkin || invokePointerHover);
// this is essential for push and other things to work in the simulator
Preferences p = Preferences.userNodeForPackage(com.codename1.ui.Component.class);
String user = p.get("user", null);
if(user != null) {
Display d = Display.getInstance();
d.setProperty("built_by_user", user);
String mainClass = System.getProperty("MainClass");
if (mainClass != null) {
mainClass = mainClass.substring(0, mainClass.lastIndexOf('.'));
d.setProperty("package_name", mainClass);
}
}
String hide = System.getProperty("hideMenu", "false");
if (hide != null && hide.equals("true")) {
showMenu = false;
}
URLConnection.setDefaultAllowUserInteraction(true);
HttpURLConnection.setFollowRedirects(false);
final ArrayList delayedTasks = new ArrayList();
Timer delayedTasksTimer = new Timer();
TimerTask delayedTimerTask = new TimerTask() {
@Override
public void run() {
while (!delayedTasks.isEmpty()) {
EventQueue.invokeLater(delayedTasks.remove(0));
}
}
};
delayedTasksTimer.schedule(delayedTimerTask, 1000L);
if (!blockMonitors && pref.getBoolean("NetworkMonitor", false)) {
delayedTasks.add(new Runnable() {
public void run() {
showNetworkMonitor();
}
});
}
if (!blockMonitors && pref.getBoolean("PushSimulator", false)) {
pushSimulation = new PushSimulator();
pushSimulation.setVisible(true);
}
if (!blockMonitors && pref.getBoolean("PerformanceMonitor", false)) {
showPerformanceMonitor();
}
if (defaultInitTarget != null && m == null) {
m = defaultInitTarget;
}
if (canvas.getParent() != null) {
canvas.getParent().remove(canvas);
}
if (hasSkins()) {
hSelector = new JScrollBar(Scrollbar.HORIZONTAL);
vSelector = new JScrollBar(Scrollbar.VERTICAL);
hSelector.addAdjustmentListener(canvas);
vSelector.addAdjustmentListener(canvas);
}
if (hasSkins() && useAppFrame) {
appFrame = new AppFrame("Simulator") {
@Override
protected void decoratePanelWindow(AppPanel panel, Window window) {
try {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
boolean desktopSkin = pref.getBoolean("desktopSkin", false);
installMenu((JFrame) window, desktopSkin);
} catch (Exception ex) {
throw new RuntimeException("Failed to decorate panel window in app frame.", ex);
}
}
};
JPanel canvasWrapper = new JPanel();
canvasWrapper.setLayout(new BorderLayout());
canvasWrapper.add(canvas, java.awt.BorderLayout.CENTER);
canvasWrapper.setPreferredSize(new Dimension(640, 640));
scrollableSkin = pref.getBoolean("Scrollable", scrollableSkin);
if (scrollableSkin) {
canvasWrapper.add(hSelector, java.awt.BorderLayout.SOUTH);
canvasWrapper.add(vSelector, java.awt.BorderLayout.EAST);
}
componentTreeInspector = new ComponentTreeInspector();
AppPanel componentTreeInspectorPanel = new AppPanel("Components", "Components", componentTreeInspector.removeComponentTree());
componentTreeInspectorPanel.setPreferredFrame(AppFrame.FrameLocation.LeftPanel);
componentTreeInspectorPanel.addAction(componentTreeInspector.new RefreshAction());
componentTreeInspectorPanel.addAction(componentTreeInspector.new ValidateAction());
componentTreeInspectorPanel.addAction(componentTreeInspector.new ToggleInspectSimulatorAction());
AppPanel canvasPanel = new AppPanel("Simulator", "Simulator", canvasWrapper);
canvasPanel.setPreferredFrame(AppFrame.FrameLocation.CenterPanel);
RotateAction portraitAction = new RotateAction(true);
RotateAction landscapeAction = new RotateAction(false);
canvasPanel.addAction(portraitAction);
canvasPanel.addAction(landscapeAction);
ZoomAction zoomIn = new ZoomAction(true);
ZoomAction zoomOut = new ZoomAction(false);
canvasPanel.addAction(zoomIn);
canvasPanel.addAction(zoomOut);
canvasPanel.addAction(new SeparatorAction());
canvasPanel.addAction(new ScreenshotAction());
canvasPanel.addAction(new ScreenshotSettingsAction());
appFrame.registerUpdateCallback(zoomIn);
appFrame.registerUpdateCallback(zoomOut);
appFrame.registerUpdateCallback(portraitAction);
appFrame.registerUpdateCallback(landscapeAction);
AppPanel detailsPanel = new AppPanel("Details", "Component Details", componentTreeInspector);
detailsPanel.setPreferredFrame(AppFrame.FrameLocation.BottomPanel);
detailsPanel.setScrollable(false, true);
AppPanel propertiesPanel = new AppPanel("Properties", "Properties", componentTreeInspector.getPropertyDetailsPanel());
propertiesPanel.setPreferredFrame(AppFrame.FrameLocation.RightPanel);
propertiesPanel.setScrollable(false, false);
propertiesPanel.addAction(new JavaSEPort.OpenJavadocsAction());
appFrame.add(propertiesPanel);
appFrame.add(detailsPanel);
appFrame.add(canvasPanel);
appFrame.add(componentTreeInspectorPanel);
}
if (m != null && m instanceof java.awt.Container) {
java.awt.Container cnt = (java.awt.Container) m;
java.awt.Component mainContents = appFrame == null ? canvas : appFrame;
if (cnt.getLayout() instanceof java.awt.BorderLayout) {
cnt.add(java.awt.BorderLayout.CENTER, mainContents);
} else {
cnt.add(mainContents);
}
} else {
window = new JFrame();
window.setLayout(new java.awt.BorderLayout());
if (appFrame == null) {
scrollableSkin = pref.getBoolean("Scrollable", scrollableSkin);
if (scrollableSkin) {
window.add(hSelector, java.awt.BorderLayout.SOUTH);
window.add(vSelector, java.awt.BorderLayout.EAST);
}
}
java.awt.Component mainContents = appFrame == null ? canvas : appFrame;
window.add(mainContents, java.awt.BorderLayout.CENTER);
if (appFrame != null) {
window.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
appFrame.setPreferredSize(new Dimension(window.getContentPane().getSize()));
appFrame.setSize(new Dimension(window.getContentPane().getSize()));
appFrame.revalidate();
}
});
}
}
if (findTopFrame() != null && retinaScale > 1.0) {
findTopFrame().setGlassPane(new CN1GlassPane());
findTopFrame().getGlassPane().setVisible(true);
}
if(window != null){
java.awt.Image large = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/application64.png"));
java.awt.Image small = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/application48.png"));
try {
// setIconImages is only available in JDK 1.6
window.setIconImages(Arrays.asList(new java.awt.Image[] {large, small}));
} catch (Throwable err) {
window.setIconImage(small);
}
window.addWindowListener(new WindowListener() {
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
Display.getInstance().exitApplication();
}
public void windowClosed(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
});
window.addComponentListener(new ComponentAdapter() {
private void saveBounds(ComponentEvent e) {
if (e.getComponent() instanceof JFrame) {
Frame f = (JFrame)e.getComponent();
if (f.getExtendedState() == JFrame.NORMAL) {
Preferences pref = Preferences.userNodeForPackage(JavaSEPort.class);
Rectangle bounds = f.getBounds();
pref.put("window.bounds", bounds.x+","+bounds.y+","+bounds.width+","+bounds.height);
}
}
}
@Override
public void componentResized(ComponentEvent e) {
saveBounds(e);
}
@Override
public void componentMoved(ComponentEvent e) {
saveBounds(e);
}
});
window.setLocationByPlatform(true);
android6PermissionsFlag = pref.getBoolean("Android6Permissions", false);
alwaysOnTop = pref.getBoolean("AlwaysOnTop", false);
if (appFrame == null) window.setAlwaysOnTop(alwaysOnTop);
String reset = System.getProperty("resetSkins");
if(reset != null && reset.equals("true")){
System.setProperty("resetSkins", "");
pref = Preferences.userNodeForPackage(JavaSEPort.class);
pref.put("skins", DEFAULT_SKINS);
}
if (hasSkins()) {
if(m == null){
String f = System.getProperty("skin");
if (f != null) {
loadSkinFile(f, window);
} else {
String d = System.getProperty("dskin");
f = pref.get("skin", d);
loadSkinFile(f, window);
}
}else{
try{
installMenu(window, true);
}catch(Exception e){
e.printStackTrace();
}
}
} else {
Resources.setRuntimeMultiImageEnabled(true);
window.setUndecorated(true);
window.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
window.pack();
if (getSkin() != null && !scrollableSkin) {
zoomLevel = zoomLevel();
}
setPortrait(pref.getBoolean("Portrait", true));
if (getSkin() != null) {
if (scrollableSkin) {
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() / retinaScale), (int)(getSkin().getHeight() / retinaScale)));
if (window != null) {
int screenH = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
int screenW = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
float zoomY = getSkin().getHeight() > screenH ? screenH/(float)getSkin().getHeight() : 1f;
float zoomX = getSkin().getWidth() > screenW ? screenW/(float)getSkin().getWidth() : 1f;
float zoom = Math.min(1,Math.min(zoomX, zoomY));
window.setSize(new java.awt.Dimension((int)(getSkin().getWidth() * retinaScale * zoom), (int)(getSkin().getHeight() * retinaScale * zoom)));
}
} else {
int screenH = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
int screenW = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
float zoomY = getSkin().getHeight() > screenH ? screenH/(float)getSkin().getHeight() : 1f;
float zoomX = getSkin().getWidth() > screenW ? screenW/(float)getSkin().getWidth() : 1f;
float zoom = Math.min(1, Math.min(zoomX, zoomY));
canvas.setForcedSize(new java.awt.Dimension((int)(getSkin().getWidth() * zoom), (int)(getSkin().getHeight() * zoom)));
if (window != null) {
window.setSize(new java.awt.Dimension((int)(getSkin().getWidth() * zoom), (int)(getSkin().getHeight() * zoom)));
}
}
}
String lastBounds = pref.get("window.bounds", null);
if (lastBounds != null) {
String[] parts = lastBounds.split(",");
Rectangle r = new Rectangle(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3]));
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
if (bounds.intersects(r)) {
window.setBounds(r);
}
}
window.setVisible(true);
}
if (useNativeInput) {
Display.getInstance().setDefaultVirtualKeyboard(null);
}
float factor = ((float) getDisplayHeight()) / 480.0f;
if (factor > 0 && autoAdjustFontSize && getSkin() != null) {
// set a reasonable default font size
setFontSize((int) (15.0f * factor), (int) (11.0f * factor), (int) (19.0f * factor));
}
if (m instanceof Runnable) {
Display.getInstance().callSerially((Runnable) m);
}
inInit = false;
}
protected void sizeChanged(int w, int h) {
try{
super.sizeChanged(w, h);
if(widthLabel != null){
widthLabel.setText("Width: " + w);
heightLabel.setText("Height: " + h);
widthLabel.getParent().revalidate();
canvas.blit();
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* @inheritDoc
*/
public void vibrate(int duration) {
System.out.println("vibrate(" + duration + ")");
}
/**
* @inheritDoc
*/
public void flashBacklight(int duration) {
checkEDT();
}
/**
* @inheritDoc
*/
public int getDisplayWidth() {
return getDisplayWidthImpl();
}
private int getDisplayWidthImpl() {
if (getScreenCoordinates() != null) {
return getScreenCoordinates().width ;
}
int w = (int)(canvas.getWidth() * retinaScale);
if (w < 10 && canvas.getParent() != null) {
return (int)(canvas.getParent().getWidth() * retinaScale);
}
return Math.max(w, 100);
}
/**
* @inheritDoc
*/
public int getDisplayHeight() {
return getDisplayHeightImpl();
}
private int getDisplayHeightImpl() {
if (getScreenCoordinates() != null) {
return getScreenCoordinates().height;
}
int h = (int)(canvas.getHeight() * retinaScale);
if (h < 10 && canvas.getParent() != null) {
return (int)(canvas.getParent().getHeight() * retinaScale);
}
return Math.max(h, 100);
}
/**
* Creates a soft/weak reference to an object that allows it to be collected
* yet caches it. This method is in the porting layer since CLDC only
* includes weak references while some platforms include nothing at all and
* some include the superior soft references.
*
* @param o object to cache
* @return a caching object or null if caching isn't supported
*/
public Object createSoftWeakRef(Object o) {
return new SoftReference(o);
}
/**
* Extracts the hard reference from the soft/weak reference given
*
* @param o the reference returned by createSoftWeakRef
* @return the original object submitted or null
*/
public Object extractHardRef(Object o) {
SoftReference w = (SoftReference) o;
if (w != null) {
return w.get();
}
return null;
}
@Override
public boolean isSimulator() {
// differentiate simulator from JavaSE port and detect designer
return designMode || getSkin() != null || widthLabel != null;
}
/**
* @inheritDoc
*/
public boolean isNativeInputSupported() {
checkEDT();
return useNativeInput;
}
public boolean isNativeInputImmediate() {
checkEDT();
return useNativeInput;
}
private void setText(java.awt.Component c, String text) {
if (c instanceof java.awt.TextComponent) {
((java.awt.TextComponent) c).setText(text);
} else {
((JTextComponent) c).setText(text);
}
}
private String getText(java.awt.Component c) {
if (c instanceof java.awt.TextComponent) {
return ((java.awt.TextComponent) c).getText();
} else {
return ((JTextComponent) c).getText();
}
}
private void setCaretPosition(java.awt.Component c, int p) {
if (c instanceof java.awt.TextComponent) {
((java.awt.TextComponent) c).setCaretPosition(p);
} else {
((JTextComponent) c).setCaretPosition(p);
}
}
private int getCaretPosition(java.awt.Component c) {
if (c instanceof java.awt.TextComponent) {
return ((java.awt.TextComponent) c).getCaretPosition();
} else {
return ((JTextComponent) c).getCaretPosition();
}
}
@Override
public boolean nativeEditorPaintsHint() {
return false;
}
public void editStringLegacy(final Component cmp, int maxSize, int constraint, String text, int keyCode) {
checkEDT();
java.awt.Component awtTf;
if (cmp instanceof com.codename1.ui.TextField) {
java.awt.TextField t = new java.awt.TextField();
awtTf = t;
t.setSelectionEnd(0);
t.setSelectionStart(0);
} else {
java.awt.TextArea t = new java.awt.TextArea("", 0, 0, java.awt.TextArea.SCROLLBARS_NONE);;
awtTf = t;
t.setSelectionEnd(0);
t.setSelectionStart(0);
}
final java.awt.Component tf = awtTf;
if (keyCode > 0) {
text += ((char) keyCode);
setText(tf, text);
setCaretPosition(tf, text.length());
((com.codename1.ui.TextField) cmp).setText(getText(tf));
} else {
setText(tf, text);
}
canvas.add(tf);
if (getSkin() != null) {
tf.setBounds((int) ((cmp.getAbsoluteX() + getScreenCoordinates().x + canvas.x) * zoomLevel),
(int) ((cmp.getAbsoluteY() + getScreenCoordinates().y + canvas.y) * zoomLevel),
(int) (cmp.getWidth() * zoomLevel), (int) (cmp.getHeight() * zoomLevel));
java.awt.Font f = font(cmp.getStyle().getFont().getNativeFont());
tf.setFont(f.deriveFont(f.getSize2D() * zoomLevel));
} else {
tf.setBounds(cmp.getAbsoluteX(), cmp.getAbsoluteY(), cmp.getWidth(), cmp.getHeight());
tf.setFont(font(cmp.getStyle().getFont().getNativeFont()));
}
setCaretPosition(tf, getText(tf).length());
tf.requestFocus();
class Listener implements ActionListener, FocusListener, KeyListener, TextListener, Runnable {
public synchronized void run() {
while (tf.getParent() != null) {
try {
wait(20);
} catch (InterruptedException ex) {
}
}
}
public void actionPerformed(ActionEvent e) {
String txt = getText(tf);
if (testRecorder != null) {
testRecorder.editTextFieldCompleted(cmp, txt);
}
Display.getInstance().onEditingComplete(cmp, txt);
if (tf instanceof java.awt.TextField) {
((java.awt.TextField) tf).removeActionListener(this);
}
((TextComponent) tf).removeTextListener(this);
tf.removeFocusListener(this);
canvas.remove(tf);
synchronized (this) {
notify();
}
canvas.repaint();
}
public void focusGained(FocusEvent e) {
setCaretPosition(tf, getText(tf).length());
}
public void focusLost(FocusEvent e) {
actionPerformed(null);
}
public void keyTyped(KeyEvent e) {
String t = getText(tf);
if (t.length() >= ((TextArea) cmp).getMaxSize()) {
e.consume();
}
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
if (tf instanceof java.awt.TextField) {
actionPerformed(null);
} else {
if (getCaretPosition(tf) >= getText(tf).length() - 1) {
actionPerformed(null);
}
}
return;
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
if (tf instanceof java.awt.TextField) {
actionPerformed(null);
} else {
if (getCaretPosition(tf) <= 2) {
actionPerformed(null);
}
}
return;
}
}
public void textValueChanged(TextEvent e) {
if (cmp instanceof com.codename1.ui.TextField) {
((com.codename1.ui.TextField) cmp).setText(getText(tf));
}
}
};
final Listener l = new Listener();
if (tf instanceof java.awt.TextField) {
((java.awt.TextField) tf).addActionListener(l);
}
((TextComponent) tf).addTextListener(l);
tf.addKeyListener(l);
tf.addFocusListener(l);
if(simulateAndroidKeyboard) {
java.util.Timer t = new java.util.Timer();
TimerTask tt = new TimerTask() {
@Override
public void run() {
if(!Display.getInstance().isEdt()) {
Display.getInstance().callSerially(this);
return;
}
if(tf.getParent() != null) {
final int height = getScreenCoordinates().height;
JavaSEPort.this.sizeChanged(getScreenCoordinates().width, height / 2);
new UITimer(new Runnable() {
public void run() {
if(tf.getParent() != null) {
new UITimer(this).schedule(100, false, Display.getInstance().getCurrent());
} else {
JavaSEPort.this.sizeChanged(getScreenCoordinates().width, height);
}
}
}).schedule(100, false, Display.getInstance().getCurrent());
}
}
};
t.schedule(tt, 300);
}
Display.getInstance().invokeAndBlock(l);
}
@Override
public void stopTextEditing() {
if (textCmp != null && textCmp.getParent() != null) {
canvas.remove(textCmp);
}
}
@Override
public boolean usesInvokeAndBlockForEditString() {
return false;
}
@Override
public boolean isAsyncEditMode() {
return true;
}
private interface EditingInProgress {
void invokeAfter(Runnable r);
void endEditing();
}
private EditingInProgress editingInProgress;
private Component currentlyEditingField;
private Process tabTipProcess;
/**
* @inheritDoc
*/
public void editString(final Component cmp, final int maxSize, final int constraint, String text, final int keyCode) {
if(scrollWheeling) {
return;
}
if(System.getProperty("TextCompatMode") != null) {
editStringLegacy(cmp, maxSize, constraint, text, keyCode);
return;
}
if (editingInProgress != null) {
final String fText = text;
editingInProgress.invokeAfter(new Runnable() {
public void run() {
CN.callSerially(new Runnable() {
public void run() {
editString(cmp, maxSize, constraint, fText, keyCode);
}
});
}
});
editingInProgress.endEditing();
return;
}
//a workaround to fix an issue where the previous Text Component wasn't removed properly.
//java.awt.Component [] cmps = canvas.getComponents();
//for (int i = 0; i < cmps.length; i++) {
// java.awt.Component cmp1 = cmps[i];
// if(cmp1 instanceof JScrollPane || cmp1 instanceof javax.swing.text.JTextComponent){
// canvas.remove(cmp1);
// }
//}
checkEDT();
class Repainter {
JComponent jcmp;
javax.swing.border.Border origBorder;
Repainter(JComponent jcmp) {
this.jcmp = jcmp;
}
void repaint(long tm, int x, int y, int width, int height) {
boolean oldShowEdtWarnings = showEDTWarnings;
showEDTWarnings = false;
int marginTop = 0;//cmp.getSelectedStyle().getPadding(Component.TOP);
int marginLeft = 0;//cmp.getSelectedStyle().getPadding(Component.LEFT);
int marginRight = 0;//cmp.getSelectedStyle().getPadding(Component.RIGHT);
int marginBottom = 0;//cmp.getSelectedStyle().getPadding(Component.BOTTOM);
int paddingTop = Math.round(cmp.getSelectedStyle().getPadding(Component.TOP) * zoomLevel);
int paddingLeft = Math.round(cmp.getSelectedStyle().getPadding(Component.LEFT) * zoomLevel);
int paddingRight = Math.round(cmp.getSelectedStyle().getPadding(Component.RIGHT) * zoomLevel);
int paddingBottom = Math.round(cmp.getSelectedStyle().getPadding(Component.BOTTOM) * zoomLevel);
Rectangle bounds;
if (getSkin() != null) {
bounds = new Rectangle((int) ((cmp.getAbsoluteX() + cmp.getScrollX() + getScreenCoordinates().x + canvas.x + marginLeft) * zoomLevel),
(int) ((cmp.getAbsoluteY() + cmp.getScrollY() + getScreenCoordinates().y + canvas.y + marginTop) * zoomLevel),
(int) ((cmp.getWidth() - marginLeft - marginRight) * zoomLevel),
(int) ((cmp.getHeight() - marginTop - marginBottom) * zoomLevel));
} else {
bounds = new Rectangle(cmp.getAbsoluteX() + cmp.getScrollX() + marginLeft, cmp.getAbsoluteY() + cmp.getScrollY() + marginTop, cmp.getWidth() - marginRight - marginLeft, cmp.getHeight() - marginTop - marginBottom);
}
if (!jcmp.getBounds().equals(bounds)) {
jcmp.setBounds(bounds);
if (origBorder == null) {
origBorder = jcmp.getBorder();
}
//jcmp.setBorder(BorderFactory.createCompoundBorder(
// origBorder,
// BorderFactory.createEmptyBorder(paddingTop, paddingLeft, paddingBottom, paddingRight))
//);
jcmp.setBorder( BorderFactory.createEmptyBorder(paddingTop, paddingLeft, paddingBottom, paddingRight));
}
showEDTWarnings = oldShowEdtWarnings;
Display.getInstance().callSerially(new Runnable() {
public void run() {
cmp.repaint();
}
});
}
}
javax.swing.text.JTextComponent swingT;
if (((com.codename1.ui.TextArea)cmp).isSingleLineTextArea()) {
JTextComponent t;
if((constraint & TextArea.PASSWORD) == TextArea.PASSWORD) {
t = new JPasswordField() {
Repainter repainter = new Repainter(this);
@Override
public void repaint(long tm, int x, int y, int width, int height) {
if (repainter != null) {
repainter.repaint(tm, x, y, width, height);
}
}
};
} else {
t = new JTextField() {
Repainter repainter = new Repainter(this);
@Override
public void repaint(long tm, int x, int y, int width, int height) {
if (repainter != null) {
repainter.repaint(tm, x, y, width, height);
}
}
};
/*
((JTextField)t).addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (cmp instanceof com.codename1.ui.TextField) {
final com.codename1.ui.TextField tf = (com.codename1.ui.TextField)cmp;
if (tf.getDoneListener() != null) {
Display.getInstance().callSerially(new Runnable() {
public void run() {
if (tf.getDoneListener() != null) {
tf.fireDoneEvent();
}
}
});
}
}
}
});
*/
}
swingT = t;
textCmp = swingT;
} else {
// Forward references so that we can access the scroll pane and its
// repainter from inside the JTextArea.
final Repainter[] fRepainter = new Repainter[1];
final JScrollPane[] fPane = new JScrollPane[1];
final com.codename1.ui.TextArea ta = (com.codename1.ui.TextArea)cmp;
JTextArea t = new JTextArea() {
@Override
public void repaint(long tm, int x, int y, int width, int height) {
// We need to catch JTextArea repaints in addition to the
// JScrollPane repaints because the ScrollPane doesn't seem to repaint
// enough.
if (fRepainter[0] != null && fPane[0] != null) {
Point p = SwingUtilities.convertPoint(this, x, y, fPane[0]);
fRepainter[0].repaint(tm, p.x, p.y, width, height);
}
}
};
t.setWrapStyleWord(true);
t.setLineWrap(true);
swingT = t;
JScrollPane pane = new JScrollPane(swingT){
Repainter repainter = new Repainter(this);
{
fRepainter[0] = repainter;
}
@Override
public void repaint(long tm, int x, int y, int width, int height) {
if (repainter != null) {
repainter.repaint(tm, x, y, width, height);
}
}
};
fPane[0] = pane;
if (ta.isGrowByContent()) {
pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
pane.setBorder(null);
pane.setOpaque(false);
pane.getViewport().setOpaque(false);
// Without these scrollbars, it seems terribly difficult
// to work with TextAreas that contain more text than can fit.
// Commenting these out for better usability - at least on OS X.
//pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
//pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
textCmp = pane;
}
if (cmp.isRTL()) {
textCmp.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}
DefaultCaret caret = (DefaultCaret) swingT.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
swingT.setFocusTraversalKeysEnabled(false);
TextEditUtil.setCurrentEditComponent(cmp);
final javax.swing.text.JTextComponent txt = swingT;
txt.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_TAB) {
if (e.isShiftDown()) {
TextEditUtil.editPrevTextArea();
} else {
TextEditUtil.editNextTextArea();
}
}
}
});
//swingT.setBorder(null);
swingT.setOpaque(false);
swingT.setForeground(new Color(cmp.getUnselectedStyle().getFgColor()));
swingT.setCaretColor(new Color(cmp.getUnselectedStyle().getFgColor()));
final javax.swing.text.JTextComponent tf = swingT;
if (keyCode > 0) {
text += ((char) keyCode);
setText(tf, text);
setCaretPosition(tf, text.length());
if(cmp instanceof com.codename1.ui.TextField) {
((com.codename1.ui.TextField) cmp).setText(getText(tf));
}
} else {
setText(tf, text);
}
textCmp.setBorder(null);
textCmp.setOpaque(false);
canvas.add(textCmp);
int marginTop = cmp.getSelectedStyle().getPadding(Component.TOP);
int marginLeft = cmp.getSelectedStyle().getPadding(Component.LEFT);
int marginRight = cmp.getSelectedStyle().getPadding(Component.RIGHT);
int marginBottom = cmp.getSelectedStyle().getPadding(Component.BOTTOM);
if (getSkin() != null) {
textCmp.setBounds((int) ((cmp.getAbsoluteX() + cmp.getScrollX() + getScreenCoordinates().x + canvas.x + marginLeft) * zoomLevel),
(int) ((cmp.getAbsoluteY() + cmp.getScrollY() + getScreenCoordinates().y + canvas.y + marginTop) * zoomLevel),
(int) ((cmp.getWidth() - marginLeft - marginRight) * zoomLevel),
(int) ((cmp.getHeight() - marginTop - marginBottom)* zoomLevel));
//System.out.println("Set bounds to "+textCmp.getBounds());
java.awt.Font f = font(cmp.getStyle().getFont().getNativeFont());
tf.setFont(f.deriveFont(f.getSize2D() * zoomLevel));
} else {
textCmp.setBounds(cmp.getAbsoluteX() + cmp.getScrollX() + marginLeft, cmp.getAbsoluteY() + cmp.getScrollY() + marginTop, cmp.getWidth() - marginRight - marginLeft, cmp.getHeight() - marginTop - marginBottom);
//System.out.println("Set bounds to "+textCmp.getBounds());
tf.setFont(font(cmp.getStyle().getFont().getNativeFont()));
}
if (tf instanceof JPasswordField && tf.getFont() != null && tf.getFont().getFontName().contains("Roboto")) {
java.awt.Font fallback = new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, tf.getFont().getSize());
tf.setFont(fallback);
}
setCaretPosition(tf, getText(tf).length());
// Windows Tablet Show Virtual Keyboard
// REf https://stackoverflow.com/a/25783041/2935174
final String sysroot = System.getenv("SystemRoot");
String tabTipExe = "C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe";
if(exposeFilesystem) {
final boolean useTabTip = "tabtip".equalsIgnoreCase(Display.getInstance().getProperty("javase.win.vkb", "tabtip"));
if (new File(tabTipExe).exists()) {
try {
if (useTabTip) {
//System.out.println("Opening TabTip");
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", tabTipExe);
tabTipProcess = pb.start();
} else {
//System.out.println("Opening OSK");
ProcessBuilder pb = new ProcessBuilder(sysroot + "/system32/osk.exe");
tabTipProcess = pb.start();
}
} catch (Exception e) {
System.err.println("Failed to open VKB: " + e.getMessage());
}
tf.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent arg0) {
//System.out.println("Lost focus...");
try {
if (tabTipProcess != null) {
tabTipProcess.destroy();
}
} catch (Exception ex){}
try {
if (useTabTip) {
Runtime.getRuntime().exec("cmd /c taskkill /IM TabTip.exe");
} else {
Runtime.getRuntime().exec("cmd /c taskkill /IM osk.exe");
}
} catch (IOException e) {
System.err.println("Problem closing VKB: " + e.getMessage());
}
}
@Override
public void focusGained(FocusEvent arg0) {
}
});
}
}
tf.requestFocus();
tf.setSelectionStart(0);
tf.setSelectionEnd(0);
class Listener implements ActionListener, FocusListener, KeyListener, TextListener, Runnable, DocumentListener, EditingInProgress {
private final JTextComponent textCmp;
private final JComponent swingComponentToRemove;
private boolean performed;
private boolean fireDone;
Listener(JTextComponent textCmp, JComponent swingComponentToRemove) {
this.textCmp = textCmp;
this.swingComponentToRemove = swingComponentToRemove;
if (textCmp instanceof JTextArea) {
if (((com.codename1.ui.TextArea)cmp).getDoneListener() != null) {
InputMap input = textCmp.getInputMap();
KeyStroke enter = KeyStroke.getKeyStroke("ENTER");
KeyStroke shiftEnter = KeyStroke.getKeyStroke("shift ENTER");
input.put(shiftEnter, "insert-break"); // input.get(enter)) = "insert-break"
input.put(enter, "text-submit");
ActionMap actions = textCmp.getActionMap();
actions.put("text-submit", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
fireDone = true;
Listener.this.actionPerformed(null);
}
});
}
}
}
public void run() {
while (swingComponentToRemove.getParent() != null) {
synchronized(this) {
try {
wait(20);
} catch (InterruptedException ex) {
}
}
}
EventQueue.invokeLater(new Runnable() {
public void run() {
actionPerformed(null);
}
});
}
public void actionPerformed(ActionEvent e) {
if (performed) {
return;
}
performed = true;
String txt = getText(tf);
if (testRecorder != null) {
testRecorder.editTextFieldCompleted(cmp, txt);
}
Display.getInstance().onEditingComplete(cmp, txt);
if (e != null && cmp instanceof com.codename1.ui.TextField || fireDone) {
final com.codename1.ui.TextArea cn1Tf = (com.codename1.ui.TextArea)cmp;
if (cmp != null && cn1Tf.getDoneListener() != null) {
cn1Tf.fireDoneEvent();
}
}
if (tf instanceof JTextField) {
((JTextField) tf).removeActionListener(this);
}
((JTextComponent) tf).getDocument().removeDocumentListener(this);
tf.removeFocusListener(this);
canvas.remove(swingComponentToRemove);
editingInProgress = null;
currentlyEditingField = null;
synchronized (this) {
notify();
}
canvas.repaint();
if (invokeAfter != null) {
for (Runnable r : invokeAfter) {
r.run();
}
invokeAfter = null;
}
}
public void focusGained(FocusEvent e) {
setCaretPosition(tf, getText(tf).length());
}
public void focusLost(FocusEvent e) {
actionPerformed(null);
}
public void keyTyped(KeyEvent e) {
String t = getText(tf);
if (t.length() >= ((TextArea) cmp).getMaxSize()) {
e.consume();
}
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
if (tf instanceof JTextField) {
actionPerformed(null);
} else {
if (getCaretPosition(tf) >= getText(tf).length() - 1) {
actionPerformed(null);
}
}
return;
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
if (tf instanceof JTextField) {
actionPerformed(null);
} else {
if (getCaretPosition(tf) <= 2) {
actionPerformed(null);
}
}
return;
}
}
public void textValueChanged(TextEvent e) {
//if (cmp instanceof com.codename1.ui.TextField) {
updateText();
//}
}
private void updateText() {
Display.getInstance().callSerially(new Runnable() {
public void run() {
//if(cmp instanceof com.codename1.ui.TextField) {
((com.codename1.ui.TextArea) cmp).setText(getText(tf));
//}
}
});
}
public void insertUpdate(DocumentEvent e) {
updateText();
}
public void removeUpdate(DocumentEvent e) {
updateText();
}
public void changedUpdate(DocumentEvent e) {
updateText();
}
private ArrayList invokeAfter;
@Override
public void invokeAfter(Runnable r) {
if (invokeAfter == null) {
invokeAfter = new ArrayList();
}
invokeAfter.add(r);
}
@Override
public void endEditing() {
if (!EventQueue.isDispatchThread()) {
EventQueue.invokeLater(new Runnable() {
public void run() {
endEditing();
}
});
return;
}
actionPerformed(null);
}
}
;
final Listener l = new Listener(tf, textCmp);
if (tf instanceof JTextField) {
((JTextField) tf).addActionListener(l);
}
((JTextComponent) tf).getDocument().addDocumentListener(l);
tf.addKeyListener(l);
tf.addFocusListener(l);
if(simulateAndroidKeyboard) {
java.util.Timer t = new java.util.Timer();
TimerTask tt = new TimerTask() {
@Override
public void run() {
if(!Display.getInstance().isEdt()) {
Display.getInstance().callSerially(this);
return;
}
if(tf.getParent() != null) {
final int height = getScreenCoordinates().height;
JavaSEPort.this.sizeChanged(getScreenCoordinates().width, height / 2);
new UITimer(new Runnable() {
public void run() {
if(tf.getParent() != null) {
new UITimer(this).schedule(100, false, Display.getInstance().getCurrent());
} else {
JavaSEPort.this.sizeChanged(getScreenCoordinates().width, height);
}
}
}).schedule(100, false, Display.getInstance().getCurrent());
}
}
};
t.schedule(tt, 300);
}
editingInProgress = l;
currentlyEditingField = cmp;
new Thread(l).start();
}
@Override
public boolean isEditingText(Component c) {
return currentlyEditingField == c && editingInProgress != null;
}
@Override
public boolean isEditingText() {
return editingInProgress != null;
}
/**
* @inheritDoc
*/
public void saveTextEditingState() {
}
@Override
public void edtIdle(boolean enter) {
if (isShowEDTWarnings()) {
if (enter) {
checkLastFrame();
} else {
lastIdleTime = System.currentTimeMillis();
}
}
}
private void checkLastFrame() {
long t = System.currentTimeMillis();
if (lastIdleTime > 0) {
long diff = t - lastIdleTime;
if (diff > 150) {
System.out.println("Rendering frame took too long " + diff + " milliseconds");
}
}
lastIdleTime = t;
}
/**
* @inheritDoc
*/
public void flushGraphics(int x, int y, int width, int height) {
if (isShowEDTWarnings()) {
checkEDT();
checkLastFrame();
}
canvas.blit(x, y, width, height);
}
/**
* @inheritDoc
*/
public void flushGraphics() {
if (isShowEDTWarnings()) {
checkEDT();
checkLastFrame();
}
canvas.blit();
}
/**
* @inheritDoc
*/
public void getRGB(Object nativeImage, int[] arr, int offset, int x, int y, int width, int height) {
checkEDT();
((BufferedImage) nativeImage).getRGB(x, y, width, height, arr, offset, width);
}
private BufferedImage createTrackableBufferedImage(final int width, final int height) {
return createTrackableBufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
private BufferedImage createTrackableBufferedImage(final int width, final int height, int type) {
if (perfMonitor != null) {
BufferedImage i = new BufferedImage(width, height, type) {
public void finalize() throws Throwable {
super.finalize();
if (perfMonitor != null) {
perfMonitor.removeImageRAM(width * height * 4);
}
}
};
perfMonitor.addImageRAM(width * height * 4);
return i;
} else {
return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
}
/**
* @inheritDoc
*/
public Object createImage(int[] rgb, final int width, final int height) {
BufferedImage i = createTrackableBufferedImage(width, height);
i.setRGB(0, 0, width, height, rgb, 0, width);
if (perfMonitor != null) {
perfMonitor.printToLog("Created RGB image width: " + width + " height: " + height
+ " size (bytes) " + (width * height * 4));
}
return i;
}
private BufferedImage cloneTrackableBufferedImage(BufferedImage b) {
final int width = b.getWidth();
final int height = b.getHeight();
BufferedImage n = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) {
public void finalize() throws Throwable {
super.finalize();
if (perfMonitor != null) {
perfMonitor.removeImageRAM(width * height * 4);
}
}
};
Graphics2D g2d = n.createGraphics();
g2d.drawImage(b, 0, 0, canvas);
g2d.dispose();
perfMonitor.addImageRAM(width * height * 4);
return n;
}
/**
* @inheritDoc
*/
public Object createImage(String path) throws IOException {
if (exists(path)) {
InputStream is = null;
try {
is = openInputStream(path);
return createImage(is);
} finally {
is.close();
}
}
try {
InputStream i = getResourceAsStream(clsInstance, path);
// prevents a security exception due to a JDK bug which for some stupid reason chooses
// to create a temporary file in the spi of Image IO
BufferedImage b = ImageIO.read(new MemoryCacheImageInputStream(i));
if (perfMonitor != null) {
b = cloneTrackableBufferedImage(b);
perfMonitor.printToLog("Created path image " + path + " width: " + b.getWidth() + " height: " + b.getHeight()
+ " size (bytes) " + (b.getWidth() * b.getHeight() * 4));
}
return b;
} catch (Throwable t) {
t.printStackTrace();
throw new IOException(t.toString());
}
}
/**
* @inheritDoc
*/
public Object createImage(InputStream i) throws IOException {
try {
BufferedImage b = ImageIO.read(i);
if (perfMonitor != null) {
b = cloneTrackableBufferedImage(b);
perfMonitor.printToLog("Created InputStream image width: " + b.getWidth() + " height: " + b.getHeight()
+ " size (bytes) " + (b.getWidth() * b.getHeight() * 4));
}
return b;
} catch (Throwable t) {
t.printStackTrace();
throw new IOException(t.toString());
}
}
/**
* @inheritDoc
*/
public Object createMutableImage(int width, int height, int fillColor) {
checkEDT();
if (perfMonitor != null) {
perfMonitor.printToLog("Created mutable image width: " + width + " height: " + height
+ " size (bytes) " + (width * height * 4));
}
int a = (fillColor >> 24) & 0xff;
if (a == 0xff) {
BufferedImage b = createTrackableBufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = b.createGraphics();
g.setColor(new Color(fillColor));
g.fillRect(0, 0, width, height);
g.dispose();
return b;
}
BufferedImage b = createTrackableBufferedImage(width, height);
if (a != 0) {
Graphics2D g = b.createGraphics();
g.setColor(new Color(fillColor));
g.fillRect(0, 0, width, height);
g.dispose();
}
return b;
}
/**
* @inheritDoc
*/
public boolean isAlphaMutableImageSupported() {
checkEDT();
return true;
}
/**
* @inheritDoc
*/
public Object createImage(byte[] bytes, int offset, int len) {
try {
BufferedImage b = ImageIO.read(new ByteArrayInputStream(bytes, offset, len));
if (perfMonitor != null) {
b = cloneTrackableBufferedImage(b);
perfMonitor.printToLog("Created data image width: " + b.getWidth() + " height: " + b.getHeight()
+ " data size (bytes) " + bytes.length
+ " unpacked size (bytes) " + (b.getWidth() * b.getHeight() * 4));
}
return b;
} catch (IOException ex) {
// never happens
ex.printStackTrace();
return null;
}
}
/**
* @inheritDoc
*/
public int getImageWidth(Object i) {
checkEDT();
if (i == null) {
return 0;
}
return ((BufferedImage) i).getWidth();
}
/**
* @inheritDoc
*/
public int getImageHeight(Object i) {
checkEDT();
if (i == null) {
return 0;
}
return ((BufferedImage) i).getHeight();
}
/**
* @inheritDoc
*/
public boolean isScaledImageDrawingSupported() {
checkEDT();
return true;
}
/**
* @inheritDoc
*/
public Object scale(Object nativeImage, int width, int height) {
checkEDT();
BufferedImage image = (BufferedImage) nativeImage;
int srcWidth = image.getWidth();
int srcHeight = image.getHeight();
if (perfMonitor != null) {
perfMonitor.printToLog("Scaling image from width: " + srcWidth + " height: " + srcHeight
+ " to width: " + width + " height: " + height
+ " size (bytes) " + (width * height * 4));
}
// no need to scale
if (srcWidth == width && srcHeight == height) {
return image;
}
int[] currentArray = new int[srcWidth];
int[] destinationArray = new int[width * height];
scaleArray(image, srcWidth, srcHeight, height, width, currentArray, destinationArray);
return createImage(destinationArray, width, height);
}
private void scaleArray(BufferedImage currentImage, int srcWidth, int srcHeight, int height, int width, int[] currentArray, int[] destinationArray) {
// disable EDT logging for this method
boolean edtLog = showEDTWarnings;
showEDTWarnings = false;
// Horizontal Resize
int yRatio = (srcHeight << 16) / height;
int xRatio = (srcWidth << 16) / width;
int xPos = xRatio / 2;
int yPos = yRatio / 2;
// if there is more than 16bit color there is no point in using mutable
// images since they won't save any memory
for (int y = 0; y < height; y++) {
int srcY = yPos >> 16;
getRGB(currentImage, currentArray, 0, 0, srcY, srcWidth, 1);
for (int x = 0; x < width; x++) {
int srcX = xPos >> 16;
int destPixel = x + y * width;
if ((destPixel >= 0 && destPixel < destinationArray.length) && (srcX < currentArray.length)) {
destinationArray[destPixel] = currentArray[srcX];
}
xPos += xRatio;
}
yPos += yRatio;
xPos = xRatio / 2;
}
showEDTWarnings = edtLog;
}
private static int round(double d) {
double f = Math.floor(d);
double c = Math.ceil(d);
if (c - d < d - f) {
return (int) c;
}
return (int) f;
}
/**
* @inheritDoc
*/
public Object rotate(Object image, int degrees) {
checkEDT();
int width = getImageWidth(image);
int height = getImageHeight(image);
int[] arr = new int[width * height];
int[] dest = new int[arr.length];
getRGB(image, arr, 0, 0, 0, width, height);
int centerX = width / 2;
int centerY = height / 2;
double radians = Math.toRadians(-degrees);
double cosDeg = Math.cos(radians);
double sinDeg = Math.sin(radians);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int x2 = round(cosDeg * (x - centerX) - sinDeg * (y - centerY) + centerX);
int y2 = round(sinDeg * (x - centerX) + cosDeg * (y - centerY) + centerY);
if (!(x2 < 0 || y2 < 0 || x2 >= width || y2 >= height)) {
int destOffset = x2 + y2 * width;
if (destOffset >= 0 && destOffset < dest.length) {
dest[x + y * width] = arr[destOffset];
}
}
}
}
return createImage(dest, width, height);
}
/**
* @inheritDoc
*/
public int getSoftkeyCount() {
return softkeyCount;
}
/**
* @inheritDoc
*/
public int[] getSoftkeyCode(int index) {
switch (softkeyCount) {
case 0:
return null;
case 2:
if (index == 0) {
return new int[]{KeyEvent.VK_F1};
} else {
return new int[]{KeyEvent.VK_F2};
}
default:
return new int[]{KeyEvent.VK_F1};
}
}
/**
* @inheritDoc
*/
public int getClearKeyCode() {
return KeyEvent.VK_DELETE;
}
/**
* @inheritDoc
*/
public int getBackspaceKeyCode() {
return KeyEvent.VK_BACK_SPACE;
}
/**
* @inheritDoc
*/
public int getBackKeyCode() {
return KeyEvent.VK_ESCAPE;
}
/**
* @inheritDoc
*/
public int getGameAction(int keyCode) {
switch (keyCode) {
case GAME_KEY_CODE_UP:
return Display.GAME_UP;
case GAME_KEY_CODE_DOWN:
return Display.GAME_DOWN;
case GAME_KEY_CODE_RIGHT:
return Display.GAME_RIGHT;
case GAME_KEY_CODE_LEFT:
return Display.GAME_LEFT;
case GAME_KEY_CODE_FIRE:
return Display.GAME_FIRE;
}
return 0;
}
/**
* @inheritDoc
*/
public int getKeyCode(int gameAction) {
switch (gameAction) {
case Display.GAME_UP:
return GAME_KEY_CODE_UP;
case Display.GAME_DOWN:
return GAME_KEY_CODE_DOWN;
case Display.GAME_RIGHT:
return GAME_KEY_CODE_RIGHT;
case Display.GAME_LEFT:
return GAME_KEY_CODE_LEFT;
case Display.GAME_FIRE:
return GAME_KEY_CODE_FIRE;
}
return 0;
}
/**
* @inheritDoc
*/
public boolean isTouchDevice() {
return touchDevice;
}
/**
* @inheritDoc
*/
public void setNativeFont(Object graphics, Object font) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
nativeGraphics.setFont(font(font));
}
/**
* @inheritDoc
*/
public int getClipX(Object graphics) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
java.awt.Rectangle r = nativeGraphics.getClipBounds();
if (r == null) {
return 0;
}
return r.x;
}
/**
* @inheritDoc
*/
public int getClipY(Object graphics) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
java.awt.Rectangle r = nativeGraphics.getClipBounds();
if (r == null) {
return 0;
}
return r.y;
}
/**
* @inheritDoc
*/
public int getClipWidth(Object graphics) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
java.awt.Rectangle r = nativeGraphics.getClipBounds();
if (r == null) {
if (graphics instanceof NativeScreenGraphics) {
NativeScreenGraphics ng = (NativeScreenGraphics) graphics;
if (ng.sourceImage != null) {
return ng.sourceImage.getWidth();
}
}
return getDisplayWidthImpl();
}
return r.width;
}
/**
* @inheritDoc
*/
public int getClipHeight(Object graphics) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
java.awt.Rectangle r = nativeGraphics.getClipBounds();
if (r == null) {
if (graphics instanceof NativeScreenGraphics) {
NativeScreenGraphics ng = (NativeScreenGraphics) graphics;
if (ng.sourceImage != null) {
return ng.sourceImage.getHeight();
}
}
return getDisplayHeightImpl();
}
return r.height;
}
/**
* @inheritDoc
*/
public void setClip(Object graphics, int x, int y, int width, int height) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
nativeGraphics.setClip(x, y, width, height);
if (perfMonitor != null) {
perfMonitor.setClip(x, y, width, height);
}
}
/**
* @inheritDoc
*/
public boolean isShapeClipSupported(Object graphics){
return true;
}
/**
* @inheritDoc
*/
public void setClip(Object graphics, com.codename1.ui.geom.Shape shape){
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
Shape s = cn1ShapeToAwtShape(shape);
nativeGraphics.setClip(s);
}
/**
* @inheritDoc
*/
public void clipRect(Object graphics, int x, int y, int width, int height) {
checkEDT();
Graphics2D nativeGraphics = getGraphics(graphics);
nativeGraphics.clipRect(x, y, width, height);
if (perfMonitor != null) {
perfMonitor.clipRect(x, y, width, height);
}
}
@Override
public void pushClip(Object graphics) {
checkEDT();
Graphics2D g2d = getGraphics(graphics);
Shape currentClip = g2d.getClip();
AffineTransform at = g2d.getTransform();
if (!at.isIdentity()) {
try {
at.invert();
} catch (Exception ex){}
}
currentClip = at.createTransformedShape(currentClip);
if ( graphics instanceof NativeScreenGraphics ){
NativeScreenGraphics g = (NativeScreenGraphics)graphics;
g.clipStack.push(currentClip);
} else {
synchronized(clipStack) {
if (!clipStack.containsKey(graphics)) {
clipStack.put(graphics, new LinkedList());
}
clipStack.get(graphics).push(currentClip);
}
}
}
@Override
public void popClip(Object graphics) {
checkEDT();
Graphics2D g2d = getGraphics(graphics);
if ( graphics instanceof NativeScreenGraphics ){
NativeScreenGraphics g = (NativeScreenGraphics)graphics;
Shape oldClip = g.clipStack.pop();
g2d.setClip(oldClip);
} else {
synchronized(clipStack) {
if (clipStack.containsKey(graphics)) {
Shape oldClip = clipStack.get(graphics).pop();
if (oldClip != null) {
g2d.setClip(oldClip);
}
}
}
}
}
private final Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy