From 0ee7361678fc7d03cc464ca31bf22a52bb063b2d Mon Sep 17 00:00:00 2001 From: Iurii Sergiichuk Date: Fri, 21 Aug 2015 23:01:07 +0300 Subject: [PATCH] Release 0.0.5S Added new functionality to send any possible keyEvent returned functionality to toggle orientation using "third mouse button" temporally disabled some un-useful or buggy features. code refactored. --- pom.xml | 23 +- .../screencast/api/AndroidDeviceImpl.java | 3 +- .../screencast/api/command/KeyCommand.java | 12 +- .../factory/AdbInputCommandFactory.java | 9 + .../api/injector/InputKeyEvent.java | 1 + .../api/injector/KeyCodeConverter.java | 4 +- .../api/injector/ScreenCaptureThread.java | 13 +- .../api/recording/DataAtomOutputStream.java | 26 +- .../recording/FilterImageOutputStream.java | 29 +-- .../api/recording/QuickTimeOutputStream.java | 165 +++++-------- .../app/AndroidScreencastApplication.java | 19 +- .../screencast/app/SwingApplication.java | 1 + .../screencast/ui/JDialogDeviceList.java | 1 - .../android/screencast/ui/JDialogError.java | 1 - .../screencast/ui/JDialogExecuteKeyEvent.java | 117 +++++++++ .../android/screencast/ui/JFrameMain.java | 72 +++--- .../screencast/ui/MultiLineLabelUI.java | 35 +-- .../ui/explorer/LazyLoadingTreeNode.java | 12 +- .../interaction/KeyEventDispatcherImpl.java | 14 +- .../interaction/KeyboardActionListener.java | 11 +- .../ui/interaction/MouseActionAdapter.java | 42 +++- .../MouseActionAdapterFactory.java | 5 + .../ui/model/InputKeyEventTable.java | 45 ++++ .../ui/model/InputKeyEventTableModel.java | 54 +++++ .../ui/worker/AccumulativeRunnable.java | 36 +-- .../screencast/ui/worker/SwingWorker.java | 228 ++++++------------ 26 files changed, 556 insertions(+), 422 deletions(-) create mode 100644 src/com/github/xsavikx/android/screencast/ui/JDialogExecuteKeyEvent.java create mode 100644 src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTable.java create mode 100644 src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTableModel.java diff --git a/pom.xml b/pom.xml index 02e5869..27c7b60 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 AndroidScreencast AndroidScreencast - 0.0.4S + 0.0.5S Android Screencast 4.2.0.RELEASE @@ -50,7 +50,7 @@ maven-compiler-plugin - 3.1 + 3.3 1.7 1.7 @@ -92,4 +92,23 @@ http://onejar-maven-plugin.googlecode.com/svn/mavenrepo + http://xsavikx.github.io/AndroidScreencast + + https://drone.io/github.com/xSAVIKx/AndroidScreencast + DroneIO + + + GitHub + https://github.com/xSAVIKx/AndroidScreencast/issues + + AndroidScreencast - View and control your android device on PC. + +This project gives you opportunity to use your phone even with broken screen. + +Features: + No client needed + Support for Tap and Swipe gestures + Write messages using PC keyboard + Support for landscape mode + Browse your phone files on PC \ No newline at end of file diff --git a/src/com/github/xsavikx/android/screencast/api/AndroidDeviceImpl.java b/src/com/github/xsavikx/android/screencast/api/AndroidDeviceImpl.java index 79bac80..14cfbb5 100644 --- a/src/com/github/xsavikx/android/screencast/api/AndroidDeviceImpl.java +++ b/src/com/github/xsavikx/android/screencast/api/AndroidDeviceImpl.java @@ -69,8 +69,7 @@ public List list(String path) { if (data.length < 4) continue; /* - * for(int j=0; j fillEventsWithKeyCodes(){ return eventsWithKeyCodes; } + } diff --git a/src/com/github/xsavikx/android/screencast/api/injector/KeyCodeConverter.java b/src/com/github/xsavikx/android/screencast/api/injector/KeyCodeConverter.java index c8e9504..13d5a00 100644 --- a/src/com/github/xsavikx/android/screencast/api/injector/KeyCodeConverter.java +++ b/src/com/github/xsavikx/android/screencast/api/injector/KeyCodeConverter.java @@ -1,9 +1,9 @@ package com.github.xsavikx.android.screencast.api.injector; -import org.apache.log4j.Logger; - import java.awt.event.KeyEvent; +import org.apache.log4j.Logger; + public class KeyCodeConverter { private static final Logger LOGGER = Logger.getLogger(KeyCodeConverter.class); diff --git a/src/com/github/xsavikx/android/screencast/api/injector/ScreenCaptureThread.java b/src/com/github/xsavikx/android/screencast/api/injector/ScreenCaptureThread.java index b4b29c1..e8e9ac4 100644 --- a/src/com/github/xsavikx/android/screencast/api/injector/ScreenCaptureThread.java +++ b/src/com/github/xsavikx/android/screencast/api/injector/ScreenCaptureThread.java @@ -1,7 +1,5 @@ package com.github.xsavikx.android.screencast.api.injector; -import org.apache.log4j.Logger; - import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; @@ -10,6 +8,7 @@ import javax.swing.SwingUtilities; +import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -43,7 +42,6 @@ public ScreenCaptureThread() { } public void display(RawImage rawImage) { - int width2 = landscape ? rawImage.height : rawImage.width; int height2 = landscape ? rawImage.width : rawImage.height; if (image == null) { @@ -78,13 +76,9 @@ public void display(RawImage rawImage) { if (listener != null) { SwingUtilities.invokeLater(new Runnable() { - @Override public void run() { - listener.handleNewImage(size, image, landscape); - // jp.handleNewImage(size, image, landscape); - } }); } @@ -103,8 +97,6 @@ private boolean fetchImage() throws IOException { } return true; } - - // System.out.println("Getting initial screenshot through ADB"); RawImage rawImage = null; synchronized (device) { try { @@ -114,13 +106,12 @@ private boolean fetchImage() throws IOException { } } if (rawImage != null) { - // System.out.println("screenshot through ADB ok"); display(rawImage); } else { LOGGER.info("failed getting screenshot through ADB ok"); } try { - Thread.sleep(10); + Thread.sleep(5); } catch (InterruptedException e) { LOGGER.error("fetchImage()", e); return false; diff --git a/src/com/github/xsavikx/android/screencast/api/recording/DataAtomOutputStream.java b/src/com/github/xsavikx/android/screencast/api/recording/DataAtomOutputStream.java index 2114114..5552fef 100644 --- a/src/com/github/xsavikx/android/screencast/api/recording/DataAtomOutputStream.java +++ b/src/com/github/xsavikx/android/screencast/api/recording/DataAtomOutputStream.java @@ -12,8 +12,7 @@ public class DataAtomOutputStream extends FilterOutputStream { protected static final long MAC_TIMESTAMP_EPOCH = new GregorianCalendar(1904, Calendar.JANUARY, 1).getTimeInMillis(); /** - * The number of bytes written to the data output stream so far. If this - * counter overflows, it will be wrapped to Integer.MAX_VALUE. + * The number of bytes written to the data output stream so far. If this counter overflows, it will be wrapped to Integer.MAX_VALUE. */ protected long written; @@ -22,8 +21,7 @@ public DataAtomOutputStream(OutputStream out) { } /** - * Increases the written counter by the specified value until it reaches - * Long.MAX_VALUE. + * Increases the written counter by the specified value until it reaches Long.MAX_VALUE. */ protected void incCount(int value) { long temp = written + value; @@ -34,8 +32,7 @@ protected void incCount(int value) { } /** - * Returns the current value of the counter written, the number - * of bytes written to this data output stream so far. If the counter + * Returns the current value of the counter written, the number of bytes written to this data output stream so far. If the counter * overflows, it will be wrapped to Integer.MAX_VALUE. * * @return the value of the written field. @@ -46,10 +43,8 @@ public final long size() { } /** - * Writes len bytes from the specified byte array starting at - * offset off to the underlying output stream. If no exception is - * thrown, the counter written is incremented by len - * . + * Writes len bytes from the specified byte array starting at offset off to the underlying output stream. If no exception + * is thrown, the counter written is incremented by len . * * @param b * the data. @@ -68,9 +63,8 @@ public synchronized void write(byte b[], int off, int len) throws IOException { } /** - * Writes the specified byte (the low eight bits of the argument - * b) to the underlying output stream. If no exception is thrown, - * the counter written is incremented by 1 . + * Writes the specified byte (the low eight bits of the argument b) to the underlying output stream. If no exception is thrown, the + * counter written is incremented by 1 . *

* Implements the write method of OutputStream. * @@ -116,8 +110,7 @@ public void writeBCD4(int v) throws IOException { } /** - * Writes out a byte to the underlying output stream as a 1-byte - * value. If no exception is thrown, the counter written is + * Writes out a byte to the underlying output stream as a 1-byte value. If no exception is thrown, the counter written is * incremented by 1. * * @param v @@ -198,8 +191,7 @@ public void writeFixed8D8(float f) throws IOException { } /** - * Writes an int to the underlying output stream as four bytes, - * high byte first. If no exception is thrown, the counter + * Writes an int to the underlying output stream as four bytes, high byte first. If no exception is thrown, the counter * written is incremented by 4. * * @param v diff --git a/src/com/github/xsavikx/android/screencast/api/recording/FilterImageOutputStream.java b/src/com/github/xsavikx/android/screencast/api/recording/FilterImageOutputStream.java index a158c6e..7baaaac 100644 --- a/src/com/github/xsavikx/android/screencast/api/recording/FilterImageOutputStream.java +++ b/src/com/github/xsavikx/android/screencast/api/recording/FilterImageOutputStream.java @@ -14,12 +14,10 @@ public FilterImageOutputStream(ImageOutputStream iOut) { } /** - * Closes this output stream and releases any system resources associated with - * the stream. + * Closes this output stream and releases any system resources associated with the stream. *

- * The close method of FilterOutputStream calls its - * flush method, and then calls the close method of - * its underlying output stream. + * The close method of FilterOutputStream calls its flush method, and then calls the close + * method of its underlying output stream. * * @exception IOException * if an I/O error occurs. @@ -33,11 +31,9 @@ public void close() throws IOException { } /** - * Flushes this output stream and forces any buffered output bytes to be - * written out to the stream. + * Flushes this output stream and forces any buffered output bytes to be written out to the stream. *

- * The flush method of FilterOutputStream calls the - * flush method of its underlying output stream. + * The flush method of FilterOutputStream calls the flush method of its underlying output stream. * * @exception IOException * if an I/O error occurs. @@ -50,17 +46,13 @@ public void flush() { } /** - * Writes len bytes from the specified byte array - * starting at offset off to this output stream. + * Writes len bytes from the specified byte array starting at offset off to this output stream. *

- * The write method of FilterOutputStream calls the - * write method of one argument on each byte to + * The write method of FilterOutputStream calls the write method of one argument on each byte to * output. *

- * Note that this method does not call the write method of its - * underlying input stream with the same arguments. Subclasses of - * FilterOutputStream should provide a more efficient - * implementation of this method. + * Note that this method does not call the write method of its underlying input stream with the same arguments. Subclasses of + * FilterOutputStream should provide a more efficient implementation of this method. * * @param b * the data. @@ -80,8 +72,7 @@ public void write(byte b[], int off, int len) throws IOException { /** * Writes the specified byte to this output stream. *

- * The write method of FilterOutputStream calls the - * write method of its underlying output stream, that is, it + * The write method of FilterOutputStream calls the write method of its underlying output stream, that is, it * performs out.write(b). *

* Implements the abstract write method of OutputStream. diff --git a/src/com/github/xsavikx/android/screencast/api/recording/QuickTimeOutputStream.java b/src/com/github/xsavikx/android/screencast/api/recording/QuickTimeOutputStream.java index 2f2a031..3da662d 100644 --- a/src/com/github/xsavikx/android/screencast/api/recording/QuickTimeOutputStream.java +++ b/src/com/github/xsavikx/android/screencast/api/recording/QuickTimeOutputStream.java @@ -67,8 +67,7 @@ private class CompositeAtom extends Atom { private boolean finished; /** - * Creates a new CompositeAtom at the current position of the - * ImageOutputStream. + * Creates a new CompositeAtom at the current position of the ImageOutputStream. * * @param type * The type of the atom. @@ -87,8 +86,7 @@ public void add(Atom child) throws IOException { } /** - * Writes the atom and all its children to the ImageOutputStream and - * disposes of all resources held by the atom. + * Writes the atom and all its children to the ImageOutputStream and disposes of all resources held by the atom. * * @throws java.io.IOException */ @@ -169,8 +167,7 @@ public void finish() throws IOException { } /** - * Returns the offset of this atom to the beginning of the random access - * file + * Returns the offset of this atom to the beginning of the random access file * * @return */ @@ -192,8 +189,7 @@ public long size() { } /** - * QuickTime stores media data in samples. A sample is a single element in a - * sequence of time-ordered data. Samples are stored in the mdat atom. + * QuickTime stores media data in samples. A sample is a single element in a sequence of time-ordered data. Samples are stored in the mdat atom. */ private static class Sample { @@ -286,8 +282,7 @@ public void finish() throws IOException { } /** - * Returns the offset of this atom to the beginning of the random access - * file + * Returns the offset of this atom to the beginning of the random access file * * @return */ @@ -330,20 +325,17 @@ public long size() { private Date creationTime; /** - * Width of the video frames. All frames must have the same width. The value - * -1 is used to mark unspecified width. + * Width of the video frames. All frames must have the same width. The value -1 is used to mark unspecified width. */ private int imgWidth = -1; /** - * Height of the video frames. All frames must have the same height. The value - * -1 is used to mark unspecified height. + * Height of the video frames. All frames must have the same height. The value -1 is used to mark unspecified height. */ private int imgHeight = -1; /** - * The timeScale of the movie. A time value that indicates the time scale for - * this media-that is, the number of time units that pass per second in its - * time coordinate system. + * The timeScale of the movie. A time value that indicates the time scale for this media-that is, the number of time units that pass per second in + * its time coordinate system. */ private int timeScale = 600; @@ -363,8 +355,7 @@ public long size() { private WideDataAtom mdatAtom; /** - * Creates a new output stream with the specified image videoFormat and - * framerate. + * Creates a new output stream with the specified image videoFormat and framerate. * * @param file * the output file @@ -428,13 +419,11 @@ private void ensureStarted() throws IOException { } /** - * Finishes writing the contents of the QuickTime output stream without - * closing the underlying stream. Use this method when applying multiple + * Finishes writing the contents of the QuickTime output stream without closing the underlying stream. Use this method when applying multiple * filters in succession to the same output stream. * * @exception IllegalStateException - * if the dimension of the video track has not been specified or - * determined yet. + * if the dimension of the video track has not been specified or determined yet. * @exception IOException * if an I/O exception has occurred */ @@ -470,8 +459,7 @@ public float getVideoCompressionQuality() { } /** - * Sets the time scale for this media, that is, the number of time units that - * pass per second in its time coordinate system. + * Sets the time scale for this media, that is, the number of time units that pass per second in its time coordinate system. *

* The default value is 600. * @@ -485,12 +473,10 @@ public void setTimeScale(int newValue) { } /** - * Sets the compression quality of the video track. A value of 0 stands for - * "high compression is important" a value of 1 for + * Sets the compression quality of the video track. A value of 0 stands for "high compression is important" a value of 1 for * "high image quality is important". *

- * Changing this value affects frames which are subsequently written to the - * QuickTimeOutputStream. Frames which have already been written are not + * Changing this value affects frames which are subsequently written to the QuickTimeOutputStream. Frames which have already been written are not * changed. *

* This value has no effect on videos encoded with the PNG format. @@ -506,11 +492,9 @@ public void setVideoCompressionQuality(float newValue) { /** * Sets the dimension of the video track. *

- * You need to explicitly set the dimension, if you add all frames from files - * or input streams. + * You need to explicitly set the dimension, if you add all frames from files or input streams. *

- * If you add frames from buffered images, then QuickTimeOutputStream can - * determine the video dimension from the image width and height. + * If you add frames from buffered images, then QuickTimeOutputStream can determine the video dimension from the image width and height. * * @param width * @param height @@ -536,16 +520,12 @@ private void writeEpilog() throws IOException { CompositeAtom moovAtom = new CompositeAtom("moov"); /* - * Movie Header Atom ------------- The data contained in this atom defines - * characteristics of the entire QuickTime movie, such as time scale and + * Movie Header Atom ------------- The data contained in this atom defines characteristics of the entire QuickTime movie, such as time scale and * duration. It has an atom type value of 'mvhd'. * - * typedef struct { byte version; byte[3] flags; mactimestamp creationTime; - * mactimestamp modificationTime; int timeScale; int duration; int - * preferredRate; short preferredVolume; byte[10] reserved; int[9] matrix; - * int previewTime; int previewDuration; int posterTime; int selectionTime; - * int selectionDuration; int currentTime; int nextTrackId; } - * movieHeaderAtom; + * typedef struct { byte version; byte[3] flags; mactimestamp creationTime; mactimestamp modificationTime; int timeScale; int duration; int + * preferredRate; short preferredVolume; byte[10] reserved; int[9] matrix; int previewTime; int previewDuration; int posterTime; int + * selectionTime; int selectionDuration; int currentTime; int nextTrackId; } movieHeaderAtom; */ leaf = new DataAtom("mvhd"); moovAtom.add(leaf); @@ -635,17 +615,13 @@ private void writeEpilog() throws IOException { moovAtom.add(trakAtom); /* - * Track Header Atom ----------- The track header atom specifies the - * characteristics of a single track within a movie. A track header atom - * contains a size field that specifies the number of bytes and a type field - * that indicates the format of the data (defined by the atom type 'tkhd'). + * Track Header Atom ----------- The track header atom specifies the characteristics of a single track within a movie. A track header atom + * contains a size field that specifies the number of bytes and a type field that indicates the format of the data (defined by the atom type + * 'tkhd'). * - * typedef struct { byte version; byte flag0; byte flag1; byte set - * TrackHeaderFlags flag2; mactimestamp creationTime; mactimestamp - * modificationTime; int trackId; byte[4] reserved; int duration; byte[8] - * reserved; short layer; short alternateGroup; short volume; byte[2] - * reserved; int[9] matrix; int trackWidth; int trackHeight; } - * trackHeaderAtom; + * typedef struct { byte version; byte flag0; byte flag1; byte set TrackHeaderFlags flag2; mactimestamp creationTime; mactimestamp + * modificationTime; int trackId; byte[4] reserved; int duration; byte[8] reserved; short layer; short alternateGroup; short volume; byte[2] + * reserved; int[9] matrix; int trackWidth; int trackHeight; } trackHeaderAtom; */ leaf = new DataAtom("tkhd"); trakAtom.add(leaf); @@ -751,9 +727,8 @@ private void writeEpilog() throws IOException { trakAtom.add(mdiaAtom); /* - * Media Header atom ------- typedef struct { byte version; byte[3] flags; - * mactimestamp creationTime; mactimestamp modificationTime; int timeScale; - * int duration; short language; short quality; } mediaHeaderAtom; + * Media Header atom ------- typedef struct { byte version; byte[3] flags; mactimestamp creationTime; mactimestamp modificationTime; int + * timeScale; int duration; short language; short quality; } mediaHeaderAtom; */ leaf = new DataAtom("mdhd"); mdiaAtom.add(leaf); @@ -799,8 +774,7 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("hdlr"); mdiaAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; magic componentType; magic - * componentSubtype; magic componentManufacturer; int componentFlags; int + * typedef struct { byte version; byte[3] flags; magic componentType; magic componentSubtype; magic componentManufacturer; int componentFlags; int * componentFlagsMask; cstring componentName; } handlerReferenceAtom; */ d = leaf.getOutputStream(); @@ -847,8 +821,7 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("vmhd"); minfAtom.add(leaf); /* - * typedef struct { byte version; byte flag1; byte flag2; byte set vmhdFlags - * flag3; short graphicsMode; ushort[3] opcolor; } + * typedef struct { byte version; byte flag1; byte flag2; byte set vmhdFlags flag3; short graphicsMode; ushort[3] opcolor; } * videoMediaInformationHeaderAtom; */ d = leaf.getOutputStream(); @@ -886,8 +859,7 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("hdlr"); minfAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; magic componentType; magic - * componentSubtype; magic componentManufacturer; int componentFlags; int + * typedef struct { byte version; byte[3] flags; magic componentType; magic componentSubtype; magic componentManufacturer; int componentFlags; int * componentFlagsMask; cstring componentName; } handlerReferenceAtom; */ d = leaf.getOutputStream(); @@ -935,14 +907,11 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("dref"); dinfAtom.add(leaf); /* - * typedef struct { ubyte version; ubyte[3] flags; int numberOfEntries; - * dataReferenceEntry dataReference[numberOfEntries]; } dataReferenceAtom; + * typedef struct { ubyte version; ubyte[3] flags; int numberOfEntries; dataReferenceEntry dataReference[numberOfEntries]; } dataReferenceAtom; * - * set { dataRefSelfReference=1 // I am not shure if this is the correct - * value for this flag } drefEntryFlags; + * set { dataRefSelfReference=1 // I am not shure if this is the correct value for this flag } drefEntryFlags; * - * typedef struct { int size; magic type; byte version; ubyte flag1; ubyte - * flag2; ubyte set drefEntryFlags flag3; byte[size - 12] data; } + * typedef struct { int size; magic type; byte version; ubyte flag1; ubyte flag2; ubyte set drefEntryFlags flag3; byte[size - 12] data; } * dataReferenceEntry; */ d = leaf.getOutputStream(); @@ -996,16 +965,12 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("stsd"); stblAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; int numberOfEntries; - * sampleDescriptionEntry sampleDescriptionTable[numberOfEntries]; } + * typedef struct { byte version; byte[3] flags; int numberOfEntries; sampleDescriptionEntry sampleDescriptionTable[numberOfEntries]; } * sampleDescriptionAtom; * - * typedef struct { int size; magic type; byte[6] reserved; // six bytes - * that must be zero short dataReferenceIndex; // A 16-bit integer that - * contains the index of the data reference to use to retrieve data - * associated with samples that use this sample description. Data references - * are stored in data reference atoms. byte[size - 16] data; } - * sampleDescriptionEntry; + * typedef struct { int size; magic type; byte[6] reserved; // six bytes that must be zero short dataReferenceIndex; // A 16-bit integer that + * contains the index of the data reference to use to retrieve data associated with samples that use this sample description. Data references are + * stored in data reference atoms. byte[size - 16] data; } sampleDescriptionEntry; */ d = leaf.getOutputStream(); d.write(0); // version @@ -1297,11 +1262,9 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("stts"); stblAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; int numberOfEntries; - * timeToSampleTable timeToSampleTable[numberOfEntries]; } timeToSampleAtom; + * typedef struct { byte version; byte[3] flags; int numberOfEntries; timeToSampleTable timeToSampleTable[numberOfEntries]; } timeToSampleAtom; * - * typedef struct { int sampleCount; int sampleDuration; } - * timeToSampleTable; + * typedef struct { int sampleCount; int sampleDuration; } timeToSampleTable; */ d = leaf.getOutputStream(); d.write(0); // version @@ -1360,12 +1323,9 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("stsc"); stblAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; int numberOfEntries; - * sampleToChunkTable sampleToChunkTable[numberOfEntries]; } - * sampleToChunkAtom; + * typedef struct { byte version; byte[3] flags; int numberOfEntries; sampleToChunkTable sampleToChunkTable[numberOfEntries]; } sampleToChunkAtom; * - * typedef struct { int firstChunk; int samplesPerChunk; int - * sampleDescription; } sampleToChunkTable; + * typedef struct { int firstChunk; int samplesPerChunk; int sampleDescription; } sampleToChunkTable; */ d = leaf.getOutputStream(); d.write(0); // version @@ -1401,8 +1361,7 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("stsz"); stblAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; int sampleSize; int - * numberOfEntries; sampleSizeTable sampleSizeTable[numberOfEntries]; } + * typedef struct { byte version; byte[3] flags; int sampleSize; int numberOfEntries; sampleSizeTable sampleSizeTable[numberOfEntries]; } * sampleSizeAtom; * * typedef struct { int size; } sampleSizeTable; @@ -1445,8 +1404,7 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("stco"); stblAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; int numberOfEntries; - * chunkOffsetTable chunkOffsetTable[numberOfEntries]; } chunkOffsetAtom; + * typedef struct { byte version; byte[3] flags; int numberOfEntries; chunkOffsetTable chunkOffsetTable[numberOfEntries]; } chunkOffsetAtom; * * typedef struct { int offset; } chunkOffsetTable; */ @@ -1476,9 +1434,7 @@ private void writeEpilog() throws IOException { leaf = new DataAtom("co64"); stblAtom.add(leaf); /* - * typedef struct { byte version; byte[3] flags; int numberOfEntries; - * chunkOffsetTable chunkOffset64Table[numberOfEntries]; } - * chunkOffset64Atom; + * typedef struct { byte version; byte[3] flags; int numberOfEntries; chunkOffsetTable chunkOffset64Table[numberOfEntries]; } chunkOffset64Atom; * * typedef struct { long offset; } chunkOffset64Table; */ @@ -1511,8 +1467,7 @@ private void writeEpilog() throws IOException { /** * Writes a frame to the video track. *

- * If the dimension of the video track has not been specified yet, it is - * derived from the first buffered image added to the QuickTimeOutputStream. + * If the dimension of the video track has not been specified yet, it is derived from the first buffered image added to the QuickTimeOutputStream. * * @param image * The frame image. @@ -1520,8 +1475,7 @@ private void writeEpilog() throws IOException { * The duration of the frame in time scale units. * * @throws IllegalArgumentException - * if the duration is less than 1, or if the dimension of the frame - * does not match the dimension of the video track. + * if the duration is less than 1, or if the dimension of the frame does not match the dimension of the video track. * @throws IOException * if writing the image failed. */ @@ -1596,13 +1550,11 @@ public void writeFrame(BufferedImage image, int duration) throws IOException { /** * Writes a frame from a file to the video track. *

- * This method does not inspect the contents of the file. The contents has to - * match the video format. For example, it is your responsibility to only add - * JPG files if you have chosen the JPEG video format. + * This method does not inspect the contents of the file. The contents has to match the video format. For example, it is your responsibility to only + * add JPG files if you have chosen the JPEG video format. *

- * If you add all frames from files or from input streams, then you have to - * explicitly set the dimension of the video track before you call finish() or - * close(). + * If you add all frames from files or from input streams, then you have to explicitly set the dimension of the video track before you call finish() + * or close(). * * @param file * The file which holds the image data. @@ -1624,13 +1576,11 @@ public void writeFrame(File file, int duration) throws IOException { /** * Writes a frame to the video track. *

- * This method does not inspect the contents of the input stream. The contents - * has to match the video format. For example, it is your responsibility to - * only add JPG files if you have chosen the JPEG video format. + * This method does not inspect the contents of the input stream. The contents has to match the video format. For example, it is your responsibility + * to only add JPG files if you have chosen the JPEG video format. *

- * If you add all frames from files or from input streams, then you have to - * explicitly set the dimension of the video track before you call finish() or - * close(). + * If you add all frames from files or from input streams, then you have to explicitly set the dimension of the video track before you call finish() + * or close(). * * @param in * The input stream which holds the image data. @@ -1665,8 +1615,7 @@ private void writeProlog() throws IOException { /* * File type atom * - * typedef struct { magic brand; bcd4 versionYear; bcd2 versionMonth; bcd2 - * versionMinor; magic[4] compatibleBrands; } ftypAtom; + * typedef struct { magic brand; bcd4 versionYear; bcd2 versionMonth; bcd2 versionMinor; magic[4] compatibleBrands; } ftypAtom; */ DataAtom ftypAtom = new DataAtom("ftyp"); DataAtomOutputStream d = ftypAtom.getOutputStream(); diff --git a/src/com/github/xsavikx/android/screencast/app/AndroidScreencastApplication.java b/src/com/github/xsavikx/android/screencast/app/AndroidScreencastApplication.java index b3fdbf1..426499a 100644 --- a/src/com/github/xsavikx/android/screencast/app/AndroidScreencastApplication.java +++ b/src/com/github/xsavikx/android/screencast/app/AndroidScreencastApplication.java @@ -1,5 +1,7 @@ package com.github.xsavikx.android.screencast.app; +import javax.swing.SwingUtilities; + import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; @@ -46,15 +48,18 @@ public void close() { @Override public void start() { LOGGER.debug("start() - start"); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // Start showing the device screen + jf.setTitle("" + device); - // Start showing the device screen - jf.setTitle("" + device); - - // Show window - jf.setVisible(true); - - jf.launchInjector(); + // Show window + jf.setVisible(true); + jf.launchInjector(); + } + }); LOGGER.debug("start() - end"); } diff --git a/src/com/github/xsavikx/android/screencast/app/SwingApplication.java b/src/com/github/xsavikx/android/screencast/app/SwingApplication.java index 8bfa17f..c354b3f 100644 --- a/src/com/github/xsavikx/android/screencast/app/SwingApplication.java +++ b/src/com/github/xsavikx/android/screencast/app/SwingApplication.java @@ -1,4 +1,5 @@ package com.github.xsavikx.android.screencast.app; + import java.io.PrintWriter; import java.io.StringWriter; diff --git a/src/com/github/xsavikx/android/screencast/ui/JDialogDeviceList.java b/src/com/github/xsavikx/android/screencast/ui/JDialogDeviceList.java index b9ed471..ded501f 100644 --- a/src/com/github/xsavikx/android/screencast/ui/JDialogDeviceList.java +++ b/src/com/github/xsavikx/android/screencast/ui/JDialogDeviceList.java @@ -14,7 +14,6 @@ import javax.swing.JFormattedTextField; import javax.swing.JList; import javax.swing.JPanel; -import javax.swing.JScrollPane; import javax.swing.JTextField; import com.android.ddmlib.IDevice; diff --git a/src/com/github/xsavikx/android/screencast/ui/JDialogError.java b/src/com/github/xsavikx/android/screencast/ui/JDialogError.java index 51ec74e..cb84114 100644 --- a/src/com/github/xsavikx/android/screencast/ui/JDialogError.java +++ b/src/com/github/xsavikx/android/screencast/ui/JDialogError.java @@ -23,7 +23,6 @@ public JDialogError(Throwable ex) { pack(); setLocationRelativeTo(null); setAlwaysOnTop(true); - setAlwaysOnTop(false); } } diff --git a/src/com/github/xsavikx/android/screencast/ui/JDialogExecuteKeyEvent.java b/src/com/github/xsavikx/android/screencast/ui/JDialogExecuteKeyEvent.java new file mode 100644 index 0000000..7bfd7cf --- /dev/null +++ b/src/com/github/xsavikx/android/screencast/ui/JDialogExecuteKeyEvent.java @@ -0,0 +1,117 @@ +package com.github.xsavikx.android.screencast.ui; + +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; +import javax.swing.border.TitledBorder; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.github.xsavikx.android.screencast.api.command.executor.CommandExecutor; +import com.github.xsavikx.android.screencast.api.command.factory.AdbInputCommandFactory; +import com.github.xsavikx.android.screencast.api.injector.InputKeyEvent; +import com.github.xsavikx.android.screencast.ui.model.InputKeyEventTable; +import com.github.xsavikx.android.screencast.ui.model.InputKeyEventTableModel; + +@Component +public class JDialogExecuteKeyEvent extends JDialog { + private static final long serialVersionUID = -4152020879675916776L; + private static final int HEIGHT = 600; + private static final int WIDTH = 800; + private static final int BUTTON_HEIGHT = 20; + private static final int BUTTON_WIDTH = WIDTH >> 1 - 5; + + private static final int TITLE_COLUMN_INDEX = 1; + + private static final String EXECUTE_BUTTON_TEXT = "Execute"; + private static final String CANCEL_BUTTON_TEXT = "Cancel"; + private static final String COMMAND_LIST_TITLE_TEXT = "Commands to execute"; + private static final String NO_COMMAND_CHOSEN_WARNING_MESSAGE = "Please, select command from the list"; + private static final String NO_COMMAND_CHOSEN_WARNING_DIALOG_TITLE = "Warning"; + + @Autowired + private CommandExecutor commandExecutor; + + /** + * Launch the application. + */ + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + new JDialogExecuteKeyEvent().setVisible(true); + } + }); + } + + /** + * Create the dialog. + */ + public JDialogExecuteKeyEvent() { + setResizable(false); + setTitle("Execute key event"); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + final InputKeyEventTableModel commandList = new InputKeyEventTableModel(InputKeyEvent.values()); + final InputKeyEventTable commandListTable = new InputKeyEventTable(commandList); + + JButton executeCommandButton = new JButton(EXECUTE_BUTTON_TEXT); + executeCommandButton.setSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); + executeCommandButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int rowIndex = commandListTable.getSelectedRow(); + if (rowIndex > 0) { + final String title = (String) commandList.getValueAt(rowIndex, TITLE_COLUMN_INDEX); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + commandExecutor.execute(AdbInputCommandFactory.getKeyCommand(InputKeyEvent.valueOf(title))); + } + }); + closeDialog(); + } else { + JOptionPane.showMessageDialog(null, NO_COMMAND_CHOSEN_WARNING_MESSAGE, NO_COMMAND_CHOSEN_WARNING_DIALOG_TITLE, + JOptionPane.WARNING_MESSAGE); + } + } + }); + JButton cancelButton = new JButton(CANCEL_BUTTON_TEXT); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + closeDialog(); + } + }); + JScrollPane listScrollPane = new JScrollPane(commandListTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + listScrollPane.setPreferredSize(new Dimension(WIDTH, HEIGHT)); + listScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), + COMMAND_LIST_TITLE_TEXT, TitledBorder.CENTER, TitledBorder.TOP)); + JPanel buttonPane = new JPanel(); + buttonPane.add(executeCommandButton); + buttonPane.add(cancelButton); + buttonPane.setLayout(new GridLayout(1, 2)); + JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, listScrollPane, buttonPane); + splitPane.setEnabled(false); + getContentPane().add(splitPane); + pack(); + setLocationRelativeTo(null); + } + + private void closeDialog() { + setVisible(false); + } +} diff --git a/src/com/github/xsavikx/android/screencast/ui/JFrameMain.java b/src/com/github/xsavikx/android/screencast/ui/JFrameMain.java index 4ac67d9..7069959 100644 --- a/src/com/github/xsavikx/android/screencast/ui/JFrameMain.java +++ b/src/com/github/xsavikx/android/screencast/ui/JFrameMain.java @@ -12,7 +12,6 @@ import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JScrollPane; -import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.filechooser.FileNameExtensionFilter; @@ -38,12 +37,14 @@ public class JFrameMain extends JFrame { private JPanelScreen jp = new JPanelScreen(); private JToolBar jtb = new JToolBar(); private JToolBar jtbHardkeys = new JToolBar(); - private JToggleButton jtbRecord = new JToggleButton("Record"); + // private JToggleButton jtbRecord = new JToggleButton("Record"); - private JButton jbOpenUrl = new JButton("Open Url"); + // private JButton jbOpenUrl = new JButton("Open Url"); private JScrollPane jsp; private JButton jbExplorer = new JButton("Explore"); private JButton jbRestartClient = new JButton("Restart client"); + private JButton jbExecuteKeyEvent = new JButton("Execute keycode"); + private JButton jbKbHome = new JButton("Home"); private JButton jbKbMenu = new JButton("Menu"); private JButton jbKbBack = new JButton("Back"); @@ -55,7 +56,7 @@ public class JFrameMain extends JFrame { private AndroidDevice androidDevice; private Injector injector; private Environment env; - private Dimension oldImageDimension = null; + private Dimension oldImageDimension; @Autowired public JFrameMain(Environment env, Injector injector, AndroidDevice androidDevice) { @@ -80,8 +81,8 @@ public void initialize() { jtb.setFocusable(false); jbExplorer.setFocusable(false); - jtbRecord.setFocusable(false); - jbOpenUrl.setFocusable(false); + // jtbRecord.setFocusable(false); + // jbOpenUrl.setFocusable(false); jbKbHome.setFocusable(false); jbKbMenu.setFocusable(false); jbKbBack.setFocusable(false); @@ -89,6 +90,7 @@ public void initialize() { jbKbPhoneOn.setFocusable(false); jbKbPhoneOff.setFocusable(false); jbRestartClient.setFocusable(false); + jbExecuteKeyEvent.setFocusable(false); jbKbHome.addActionListener(KeyboardActionListenerFactory.getInstance(InputKeyEvent.KEYCODE_HOME)); jbKbMenu.addActionListener(KeyboardActionListenerFactory.getInstance(InputKeyEvent.KEYCODE_MENU)); @@ -116,25 +118,25 @@ public void initialize() { pack(); setLocationRelativeTo(null); setPrefferedWindowSize(); - MouseAdapter ma = MouseActionAdapterFactory.getInstance(jp); + MouseAdapter ma = MouseActionAdapterFactory.getInstance(jp, injector); jp.addMouseMotionListener(ma); jp.addMouseListener(ma); jp.addMouseWheelListener(ma); - jtbRecord.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - if (jtbRecord.isSelected()) { - startRecording(); - } else { - stopRecording(); - } - } - - }); - jtb.add(jtbRecord); + // jtbRecord.addActionListener(new ActionListener() { + // + // @Override + // public void actionPerformed(ActionEvent arg0) { + // if (jtbRecord.isSelected()) { + // startRecording(); + // } else { + // stopRecording(); + // } + // } + // + // }); + // jtb.add(jtbRecord); jbExplorer.addActionListener(new ActionListener() { @@ -150,18 +152,30 @@ public void actionPerformed(ActionEvent arg0) { jtb.add(jbRestartClient); - jbOpenUrl.addActionListener(new ActionListener() { + jbExecuteKeyEvent.addActionListener(new ActionListener() { + @Override - public void actionPerformed(ActionEvent arg0) { - JDialogUrl jdUrl = new JDialogUrl(); - jdUrl.setVisible(true); - if (!jdUrl.isResult()) - return; - String url = jdUrl.getJtfUrl().getText(); - androidDevice.openUrl(url); + public void actionPerformed(ActionEvent e) { + JDialogExecuteKeyEvent jdExecuteKeyEvent = ApplicationContextProvider.getApplicationContext() + .getBean(JDialogExecuteKeyEvent.class); + jdExecuteKeyEvent.setVisible(true); } }); - jtb.add(jbOpenUrl); + + jtb.add(jbExecuteKeyEvent); + + // jbOpenUrl.addActionListener(new ActionListener() { + // @Override + // public void actionPerformed(ActionEvent arg0) { + // JDialogUrl jdUrl = new JDialogUrl(); + // jdUrl.setVisible(true); + // if (!jdUrl.isResult()) + // return; + // String url = jdUrl.getJtfUrl().getText(); + // androidDevice.openUrl(url); + // } + // }); + // jtb.add(jbOpenUrl); } diff --git a/src/com/github/xsavikx/android/screencast/ui/MultiLineLabelUI.java b/src/com/github/xsavikx/android/screencast/ui/MultiLineLabelUI.java index a0316b9..861ae32 100644 --- a/src/com/github/xsavikx/android/screencast/ui/MultiLineLabelUI.java +++ b/src/com/github/xsavikx/android/screencast/ui/MultiLineLabelUI.java @@ -23,12 +23,9 @@ public static Dimension computeMultiLineDimension(FontMetrics fm, String[] strs) } /** - * Compute and return the location of the icons origin, the location of origin - * of the text baseline, and a possibly clipped version of the compound labels - * string. Locations are computed relative to the viewR rectangle. This - * layoutCompoundLabel() does not know how to handle LEADING/TRAILING values - * in horizontalTextPosition (they will default to RIGHT) and in - * horizontalAlignment (they will default to CENTER). Use the other version of + * Compute and return the location of the icons origin, the location of origin of the text baseline, and a possibly clipped version of the compound + * labels string. Locations are computed relative to the viewR rectangle. This layoutCompoundLabel() does not know how to handle LEADING/TRAILING + * values in horizontalTextPosition (they will default to RIGHT) and in horizontalAlignment (they will default to CENTER). Use the other version of * layoutCompoundLabel() instead. */ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon icon, int verticalAlignment, @@ -46,8 +43,7 @@ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon ico } /* - * Initialize the text bounds rectangle textR. If a null or and empty String - * was specified we substitute "" here and use 0,0,0,0 for textR. + * Initialize the text bounds rectangle textR. If a null or and empty String was specified we substitute "" here and use 0,0,0,0 for textR. */ // Fix for textIsEmpty sent by Paulo Santos @@ -64,8 +60,7 @@ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon ico } /* - * Unless both text and icon are non-null, we effectively ignore the value - * of textIconGap. The code that follows uses the value of gap instead of + * Unless both text and icon are non-null, we effectively ignore the value of textIconGap. The code that follows uses the value of gap instead of * textIconGap. */ @@ -74,8 +69,7 @@ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon ico if (!textIsEmpty) { /* - * If the label text string is too wide to fit within the available space - * "..." and as many characters as will fit will be displayed instead. + * If the label text string is too wide to fit within the available space "..." and as many characters as will fit will be displayed instead. */ int availTextWidth; @@ -102,8 +96,7 @@ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon ico } /* - * Compute textR.x,y given the verticalTextPosition and - * horizontalTextPosition properties + * Compute textR.x,y given the verticalTextPosition and horizontalTextPosition properties */ if (verticalTextPosition == TOP) { @@ -131,11 +124,9 @@ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon ico } /* - * labelR is the rectangle that contains iconR and textR. Move it to its - * proper position given the labelAlignment properties. + * labelR is the rectangle that contains iconR and textR. Move it to its proper position given the labelAlignment properties. * - * To avoid actually allocating a Rectangle, Rectangle.union has been - * inlined below. + * To avoid actually allocating a Rectangle, Rectangle.union has been inlined below. */ int labelR_x = Math.min(iconR.x, textR.x); int labelR_width = Math.max(iconR.x + iconR.width, textR.x + textR.width) - labelR_x; @@ -174,11 +165,9 @@ public static String layoutCompoundLabel(FontMetrics fm, String[] text, Icon ico } /** - * Compute and return the location of the icons origin, the location of origin - * of the text baseline, and a possibly clipped version of the compound labels - * string. Locations are computed relative to the viewR rectangle. The - * JComponents orientation (LEADING/TRAILING) will also be taken into account - * and translated into LEFT/RIGHT values accordingly. + * Compute and return the location of the icons origin, the location of origin of the text baseline, and a possibly clipped version of the compound + * labels string. Locations are computed relative to the viewR rectangle. The JComponents orientation (LEADING/TRAILING) will also be taken into + * account and translated into LEFT/RIGHT values accordingly. */ public static String layoutCompoundLabel(JComponent c, FontMetrics fm, String[] text, Icon icon, int verticalAlignment, int horizontalAlignment, int verticalTextPosition, int horizontalTextPosition, diff --git a/src/com/github/xsavikx/android/screencast/ui/explorer/LazyLoadingTreeNode.java b/src/com/github/xsavikx/android/screencast/ui/explorer/LazyLoadingTreeNode.java index 399f1e6..bd886dc 100644 --- a/src/com/github/xsavikx/android/screencast/ui/explorer/LazyLoadingTreeNode.java +++ b/src/com/github/xsavikx/android/screencast/ui/explorer/LazyLoadingTreeNode.java @@ -23,8 +23,7 @@ public abstract class LazyLoadingTreeNode extends DefaultMutableTreeNode implements TreeWillExpandListener { /** - * ActionMap can only store one Action for the same key, This Action Stores - * the list of SwingWorker to be canceled if the escape key is pressed. + * ActionMap can only store one Action for the same key, This Action Stores the list of SwingWorker to be canceled if the escape key is pressed. * * @author Thierry LEFORT 3 mars 08 * @@ -164,8 +163,7 @@ public boolean isLeaf() { } /** - * This method will be executed in a background thread. If you have to do some - * GUI stuff use {@link SwingUtilities#invokeLater(Runnable)} + * This method will be executed in a background thread. If you have to do some GUI stuff use {@link SwingUtilities#invokeLater(Runnable)} * * @param tree * the tree @@ -174,8 +172,7 @@ public boolean isLeaf() { public abstract MutableTreeNode[] loadChildren(JTree tree); /** - * If the node is cancelable an escape Action is registered in the tree's - * InputMap and ActionMap that will cancel the execution + * If the node is cancelable an escape Action is registered in the tree's InputMap and ActionMap that will cancel the execution * * @param tree * the tree @@ -201,8 +198,7 @@ protected void registerSwingWorkerForCancel(JTree tree, SwingWorker 0 && p2.y > 0) - getCommandExecutor().execute(AdbInputCommandFactory.getTapCommand(p2.x, p2.y)); + if (injector != null && e.getButton() == MouseEvent.BUTTON3) { + injector.screencapture.toogleOrientation(); + e.consume(); + return; + } + final Point p2 = jp.getRawPoint(e.getPoint()); + if (p2.x > 0 && p2.y > 0) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + getCommandExecutor().execute(AdbInputCommandFactory.getTapCommand(p2.x, p2.y)); + + } + }); + } } @Override @@ -48,8 +64,14 @@ public void mouseDragged(MouseEvent e) { @Override public void mouseReleased(MouseEvent e) { if (timeFromPress >= ONE_SECOND) { - Point p2 = jp.getRawPoint(e.getPoint()); - getCommandExecutor().execute(AdbInputCommandFactory.getSwipeCommand(dragFromX, dragFromY, p2.x, p2.y)); + final Point p2 = jp.getRawPoint(e.getPoint()); + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + getCommandExecutor().execute(AdbInputCommandFactory.getSwipeCommand(dragFromX, dragFromY, p2.x, p2.y)); + } + }); dragFromX = -1; dragFromY = -1; timeFromPress = -1; diff --git a/src/com/github/xsavikx/android/screencast/ui/interaction/MouseActionAdapterFactory.java b/src/com/github/xsavikx/android/screencast/ui/interaction/MouseActionAdapterFactory.java index 73cce6f..407526b 100644 --- a/src/com/github/xsavikx/android/screencast/ui/interaction/MouseActionAdapterFactory.java +++ b/src/com/github/xsavikx/android/screencast/ui/interaction/MouseActionAdapterFactory.java @@ -1,9 +1,14 @@ package com.github.xsavikx.android.screencast.ui.interaction; +import com.github.xsavikx.android.screencast.api.injector.Injector; import com.github.xsavikx.android.screencast.ui.JPanelScreen; public final class MouseActionAdapterFactory { public static MouseActionAdapter getInstance(JPanelScreen jPanelScreen) { return new MouseActionAdapter(jPanelScreen); } + + public static MouseActionAdapter getInstance(JPanelScreen jPanelScreen, Injector injector) { + return new MouseActionAdapter(jPanelScreen, injector); + } } diff --git a/src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTable.java b/src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTable.java new file mode 100644 index 0000000..efb0d19 --- /dev/null +++ b/src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTable.java @@ -0,0 +1,45 @@ +package com.github.xsavikx.android.screencast.ui.model; + +import java.awt.Component; + +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +public class InputKeyEventTable extends JTable { + private static final long serialVersionUID = 3978642864003531967L; + + private final static int MIN_COLUMN_WIDTH = 20; + + public InputKeyEventTable(InputKeyEventTableModel tableModel) { + super(tableModel); + setTableColumnsNames(tableModel.columnNames); + setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + setTableColumnsPrefferedSize(); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + + private void setTableColumnsNames(String[] columnNames) { + TableColumnModel columnModel = getColumnModel(); + for (int i = 0; i < columnNames.length; i++) { + TableColumn column = columnModel.getColumn(i); + column.setHeaderValue(columnNames[i]); + } + } + + private void setTableColumnsPrefferedSize() { + final TableColumnModel columnModel = getColumnModel(); + for (int column = 0; column < getColumnCount(); column++) { + int width = MIN_COLUMN_WIDTH; // Min width + for (int row = 0; row < getRowCount(); row++) { + TableCellRenderer renderer = getCellRenderer(row, column); + Component comp = prepareRenderer(renderer, row, column); + width = Math.max(comp.getPreferredSize().width + 5, width); + } + columnModel.getColumn(column).setPreferredWidth(width); + } + } + +} diff --git a/src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTableModel.java b/src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTableModel.java new file mode 100644 index 0000000..3be911f --- /dev/null +++ b/src/com/github/xsavikx/android/screencast/ui/model/InputKeyEventTableModel.java @@ -0,0 +1,54 @@ +package com.github.xsavikx.android.screencast.ui.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.table.AbstractTableModel; + +import com.github.xsavikx.android.screencast.api.injector.InputKeyEvent; + +public class InputKeyEventTableModel extends AbstractTableModel { + private static final long serialVersionUID = 1553313932570896541L; + private final static String INDEX_COLUMN_NAME = "#"; + private final static String TITLE_COLUMN_NAME = "title"; + private final static String DESCRIPTION_COLUMN_NAME = "description"; + public final String[] columnNames = { + INDEX_COLUMN_NAME, TITLE_COLUMN_NAME, DESCRIPTION_COLUMN_NAME + }; + private List> data = new ArrayList<>(); + private int rowCount = 1; + + public InputKeyEventTableModel(InputKeyEvent[] initialData) { + initData(initialData); + } + + private void initData(InputKeyEvent[] inputKeyEvents) { + for (InputKeyEvent e : inputKeyEvents) { + data.add(getDataRow(e)); + } + } + + private List getDataRow(InputKeyEvent e) { + List row = new ArrayList<>(); + row.add(rowCount++); + row.add(e.name()); + row.add(e.getDescription()); + return row; + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + return data.get(rowIndex).get(columnIndex); + } + +} diff --git a/src/com/github/xsavikx/android/screencast/ui/worker/AccumulativeRunnable.java b/src/com/github/xsavikx/android/screencast/ui/worker/AccumulativeRunnable.java index 433a23d..e9654a3 100644 --- a/src/com/github/xsavikx/android/screencast/ui/worker/AccumulativeRunnable.java +++ b/src/com/github/xsavikx/android/screencast/ui/worker/AccumulativeRunnable.java @@ -15,21 +15,16 @@ import javax.swing.SwingUtilities; /** - * An abstract class to be used in the cases where we need {@code Runnable} to - * perform some actions on an appendable set of data. The set of data might be - * appended after the {@code Runnable} is sent for the execution. Usually such - * {@code Runnables} are sent to the EDT. + * An abstract class to be used in the cases where we need {@code Runnable} to perform some actions on an appendable set of data. The set of data + * might be appended after the {@code Runnable} is sent for the execution. Usually such {@code Runnables} are sent to the EDT. * *

* Usage example: * *

- * Say we want to implement JLabel.setText(String text) which sends {@code text} - * string to the JLabel.setTextImpl(String text) on the EDT. In the event - * JLabel.setText is called rapidly many times off the EDT we will get many - * updates on the EDT but only the last one is important. (Every next updates - * overrides the previous one.) We might want to implement this {@code setText} - * in a way that only the last update is delivered. + * Say we want to implement JLabel.setText(String text) which sends {@code text} string to the JLabel.setTextImpl(String text) on the EDT. In the + * event JLabel.setText is called rapidly many times off the EDT we will get many updates on the EDT but only the last one is important. (Every next + * updates overrides the previous one.) We might want to implement this {@code setText} in a way that only the last update is delivered. *

* Here is how one can do this using {@code AccumulativeRunnable}: * @@ -49,8 +44,7 @@ * * *

- * Say we want want to implement addDirtyRegion(Rectangle rect) which sends this - * region to the handleDirtyRegions(List regions) on the EDT. + * Say we want want to implement addDirtyRegion(Rectangle rect) which sends this region to the handleDirtyRegions(List regions) on the EDT. * addDirtyRegions better be accumulated before handling on the EDT. * *

@@ -80,11 +74,9 @@ abstract class AccumulativeRunnable implements Runnable { private List arguments = null; /** - * prepends or appends arguments and sends this {@code Runnable} for the - * execution if needed. + * prepends or appends arguments and sends this {@code Runnable} for the execution if needed. *

- * This implementation uses {@see #submit} to send this {@code Runnable} for - * execution. + * This implementation uses {@see #submit} to send this {@code Runnable} for execution. * * @param isPrepend * prepend or append @@ -108,11 +100,9 @@ public final synchronized void add(boolean isPrepend, T... args) { } /** - * appends arguments and sends this {@code Runnable} for the execution if - * needed. + * appends arguments and sends this {@code Runnable} for the execution if needed. *

- * This implementation uses {@see #submit} to send this {@code Runnable} for - * execution. + * This implementation uses {@see #submit} to send this {@code Runnable} for execution. * * @param args * the arguments to accumulate @@ -136,8 +126,7 @@ private final synchronized List flush() { * {@inheritDoc} * *

- * This implementation calls {@code run(List args)} method with the list of - * accumulated arguments. + * This implementation calls {@code run(List args)} method with the list of accumulated arguments. */ @Override public final void run() { @@ -145,8 +134,7 @@ public final void run() { } /** - * Equivalent to {@code Runnable.run} method with the accumulated arguments to - * process. + * Equivalent to {@code Runnable.run} method with the accumulated arguments to process. * * @param args * accumulated arguments to process. diff --git a/src/com/github/xsavikx/android/screencast/ui/worker/SwingWorker.java b/src/com/github/xsavikx/android/screencast/ui/worker/SwingWorker.java index 574e305..1260698 100644 --- a/src/com/github/xsavikx/android/screencast/ui/worker/SwingWorker.java +++ b/src/com/github/xsavikx/android/screencast/ui/worker/SwingWorker.java @@ -31,34 +31,26 @@ import javax.swing.Timer; /** - * An abstract class to perform lengthy GUI-interacting tasks in a dedicated - * thread. + * An abstract class to perform lengthy GUI-interacting tasks in a dedicated thread. * *

- * When writing a multi-threaded application using Swing, there are two - * constraints to keep in mind: (refer to - * - * How to Use Threads for more details): + * When writing a multi-threaded application using Swing, there are two constraints to keep in mind: (refer to + * How to Use Threads for more details): *

    - *
  • Time-consuming tasks should not be run on the Event Dispatch - * Thread. Otherwise the application becomes unresponsive.
  • - *
  • Swing components should be accessed on the Event Dispatch Thread - * only.
  • + *
  • Time-consuming tasks should not be run on the Event Dispatch Thread. Otherwise the application becomes unresponsive.
  • + *
  • Swing components should be accessed on the Event Dispatch Thread only.
  • *
* *

* *

- * These constraints mean that a GUI application with time intensive computing - * needs at least two threads: 1) a thread to perform the lengthy task and 2) - * the Event Dispatch Thread (EDT) for all GUI-related activities. This - * involves inter-thread communication which can be tricky to implement. + * These constraints mean that a GUI application with time intensive computing needs at least two threads: 1) a thread to perform the lengthy task and + * 2) the Event Dispatch Thread (EDT) for all GUI-related activities. This involves inter-thread communication which can be tricky to + * implement. * *

- * {@code SwingWorker} is designed for situations where you need to have a long - * running task run in a background thread and provide updates to the UI either - * when done, or while processing. Subclasses of {@code SwingWorker} must - * implement the {@see #doInBackground} method to perform the background + * {@code SwingWorker} is designed for situations where you need to have a long running task run in a background thread and provide updates to the UI + * either when done, or while processing. Subclasses of {@code SwingWorker} must implement the {@see #doInBackground} method to perform the background * computation. * * @@ -69,24 +61,17 @@ *

    *
  • *

    - * Current thread: The {@link #execute} method is called on this thread. - * It schedules {@code SwingWorker} for the execution on a worker thread - * and returns immediately. One can wait for the {@code SwingWorker} to complete - * using the {@link #get get} methods. + * Current thread: The {@link #execute} method is called on this thread. It schedules {@code SwingWorker} for the execution on a worker + * thread and returns immediately. One can wait for the {@code SwingWorker} to complete using the {@link #get get} methods. *

  • *

    - * Worker thread: The {@link #doInBackground} method is called on this - * thread. This is where all background activities should happen. To notify - * {@code PropertyChangeListeners} about bound properties changes use the - * {@link #firePropertyChange firePropertyChange} and - * {@link #getPropertyChangeSupport} methods. By default there are two bound - * properties available: {@code state} and {@code progress}. + * Worker thread: The {@link #doInBackground} method is called on this thread. This is where all background activities should happen. To notify + * {@code PropertyChangeListeners} about bound properties changes use the {@link #firePropertyChange firePropertyChange} and + * {@link #getPropertyChangeSupport} methods. By default there are two bound properties available: {@code state} and {@code progress}. *

  • *

    - * Event Dispatch Thread: All Swing related activities occur on this - * thread. {@code SwingWorker} invokes the {@link #process process} and - * {@link #done} methods and notifies any {@code PropertyChangeListeners} on - * this thread. + * Event Dispatch Thread: All Swing related activities occur on this thread. {@code SwingWorker} invokes the {@link #process process} and + * {@link #done} methods and notifies any {@code PropertyChangeListeners} on this thread. *

* *

@@ -94,28 +79,22 @@ * * *

- * Before the {@code doInBackground} method is invoked on a worker - * thread, {@code SwingWorker} notifies any {@code PropertyChangeListeners} - * about the {@code state} property change to {@code StateValue.STARTED}. After - * the {@code doInBackground} method is finished the {@code done} method is - * executed. Then {@code SwingWorker} notifies any - * {@code PropertyChangeListeners} about the {@code state} property change to + * Before the {@code doInBackground} method is invoked on a worker thread, {@code SwingWorker} notifies any {@code PropertyChangeListeners} + * about the {@code state} property change to {@code StateValue.STARTED}. After the {@code doInBackground} method is finished the {@code done} method + * is executed. Then {@code SwingWorker} notifies any {@code PropertyChangeListeners} about the {@code state} property change to * {@code StateValue.DONE}. * *

- * {@code SwingWorker} is only designed to be executed once. Executing a - * {@code SwingWorker} more than once will not result in invoking the + * {@code SwingWorker} is only designed to be executed once. Executing a {@code SwingWorker} more than once will not result in invoking the * {@code doInBackground} method twice. * *

* Sample Usage *

- * The following example illustrates the simplest use case. Some processing is - * done in the background and when done you update a Swing component. + * The following example illustrates the simplest use case. Some processing is done in the background and when done you update a Swing component. * *

- * Say we want to find the "Meaning of Life" and display the result in a - * {@code JLabel}. + * Say we want to find the "Meaning of Life" and display the result in a {@code JLabel}. * *

  *   final JLabel label;
@@ -138,14 +117,11 @@
  * 
* *

- * The next example is useful in situations where you wish to process data as it - * is ready on the Event Dispatch Thread. + * The next example is useful in situations where you wish to process data as it is ready on the Event Dispatch Thread. * *

- * Now we want to find the first N prime numbers and display the results in a - * {@code JTextArea}. While this is computing, we want to update our progress in - * a {@code JProgressBar}. Finally, we also want to print the prime numbers to - * {@code System.out}. + * Now we want to find the first N prime numbers and display the results in a {@code JTextArea}. While this is computing, we want to update our + * progress in a {@code JProgressBar}. Finally, we also want to print the prime numbers to {@code System.out}. * *

  * class PrimeNumbersTask extends 
@@ -190,19 +166,16 @@
  * 
* *

- * Because {@code SwingWorker} implements {@code Runnable}, a - * {@code SwingWorker} can be submitted to an - * {@link java.util.concurrent.Executor} for execution. + * Because {@code SwingWorker} implements {@code Runnable}, a {@code SwingWorker} can be submitted to an {@link java.util.concurrent.Executor} for + * execution. * * @author Igor Kushnirskiy * @version $Revision: 1.6 $ $Date: 2008/07/25 19:32:29 $ * * @param - * the result type returned by this {@code SwingWorker's} - * {@code doInBackground} and {@code get} methods + * the result type returned by this {@code SwingWorker's} {@code doInBackground} and {@code get} methods * @param - * the type used for carrying out intermediate results by this - * {@code SwingWorker's} {@code publish} and {@code process} methods + * the type used for carrying out intermediate results by this {@code SwingWorker's} {@code publish} and {@code process} methods * */ public abstract class SwingWorker implements Future, Runnable { @@ -225,8 +198,7 @@ protected void run(List args) { } finally { if (i < args.size()) { /* - * there was an exception schedule all the unhandled items for the - * next time + * there was an exception schedule all the unhandled items for the next time */ Runnable argsTail[] = new Runnable[args.size() - i]; for (int j = 0; j < argsTail.length; j++) { @@ -253,14 +225,12 @@ public enum StateValue { * Initial {@code SwingWorker} state. */ PENDING, /** - * {@code SwingWorker} is {@code STARTED} before invoking - * {@code doInBackground}. + * {@code SwingWorker} is {@code STARTED} before invoking {@code doInBackground}. */ STARTED, /** - * {@code SwingWorker} is {@code DONE} after {@code doInBackground} method - * is finished. + * {@code SwingWorker} is {@code DONE} after {@code doInBackground} method is finished. */ DONE } @@ -290,8 +260,7 @@ public void run() { /** * returns workersExecutorService. * - * returns the service stored in the appContext or creates it if necessary. If - * the last one it triggers autoShutdown thread to get started. + * returns the service stored in the appContext or creates it if necessary. If the last one it triggers autoShutdown thread to get started. * * @return ExecutorService for the {@code SwingWorkers} * @see #startAutoShutdownThread @@ -322,8 +291,7 @@ public Thread newThread(final Runnable r) { /* * We want a to have no more than MAX_WORKER_THREADS running threads. * - * We want a worker thread to wait no longer than 1 second for new tasks - * before terminating. + * We want a worker thread to wait no longer than 1 second for new tasks before terminating. */ executorService = new ThreadPoolExecutor(0, MAX_WORKER_THREADS, 5L, TimeUnit.SECONDS, new LinkedBlockingQueue(), threadFactory) { @@ -351,22 +319,15 @@ protected void afterExecute(Runnable r, Throwable t) { @Override public void execute(Runnable command) { /* - * ThreadPoolExecutor first tries to run task in a corePool. If all - * threads are busy it tries to add task to the waiting queue. If it - * fails it run task in maximumPool. + * ThreadPoolExecutor first tries to run task in a corePool. If all threads are busy it tries to add task to the waiting queue. If it fails + * it run task in maximumPool. * - * We want corePool to be 0 and maximumPool to be MAX_WORKER_THREADS - * We need to change the order of the execution. First try corePool - * then try maximumPool pool and only then store to the waiting queue. - * We can not do that because we would need access to the private - * methods. + * We want corePool to be 0 and maximumPool to be MAX_WORKER_THREADS We need to change the order of the execution. First try corePool then + * try maximumPool pool and only then store to the waiting queue. We can not do that because we would need access to the private methods. * - * Instead we enlarge corePool to MAX_WORKER_THREADS before the - * execution and shrink it back to 0 after. It does pretty much what - * we need. + * Instead we enlarge corePool to MAX_WORKER_THREADS before the execution and shrink it back to 0 after. It does pretty much what we need. * - * While we changing the corePoolSize we need to stop running worker - * threads from accepting new tasks. + * While we changing the corePoolSize we need to stop running worker threads from accepting new tasks. */ // we need atomicity for the execute method. @@ -416,8 +377,7 @@ public void execute(Runnable command) { private volatile StateValue state; /** - * everything is run inside this FutureTask. Also it is used as a delegatee - * for the Future API. + * everything is run inside this FutureTask. Also it is used as a delegatee for the Future API. */ private final FutureTask future; @@ -468,15 +428,12 @@ protected void done() { // PropertyChangeSupports methods START /** - * Adds a {@code PropertyChangeListener} to the listener list. The listener is - * registered for all properties. The same listener object may be added more - * than once, and will be called as many times as it is added. If - * {@code listener} is {@code null}, no exception is thrown and no action is + * Adds a {@code PropertyChangeListener} to the listener list. The listener is registered for all properties. The same listener object may be added + * more than once, and will be called as many times as it is added. If {@code listener} is {@code null}, no exception is thrown and no action is * taken. * *

- * Note: This is merely a convenience wrapper. All work is delegated to - * {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}. + * Note: This is merely a convenience wrapper. All work is delegated to {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}. * * @param listener * the {@code PropertyChangeListener} to be added @@ -512,12 +469,9 @@ public final boolean cancel(boolean mayInterruptIfRunning) { protected abstract T doInBackground() throws Exception; /** - * Executed on the Event Dispatch Thread after the - * {@code doInBackground} method is finished. The default implementation does - * nothing. Subclasses may override this method to perform completion actions - * on the Event Dispatch Thread. Note that you can query status inside - * the implementation of this method to determine the result of this task or - * whether this task has been cancelled. + * Executed on the Event Dispatch Thread after the {@code doInBackground} method is finished. The default implementation does nothing. + * Subclasses may override this method to perform completion actions on the Event Dispatch Thread. Note that you can query status inside the + * implementation of this method to determine the result of this task or whether this task has been cancelled. * * @see #doInBackground * @see #isCancelled() @@ -544,14 +498,11 @@ public void run() { } /** - * Schedules this {@code SwingWorker} for execution on a worker thread. - * There are a number of worker threads available. In the event all - * worker threads are busy handling other {@code SwingWorkers} this - * {@code SwingWorker} is placed in a waiting queue. + * Schedules this {@code SwingWorker} for execution on a worker thread. There are a number of worker threads available. In the event + * all worker threads are busy handling other {@code SwingWorkers} this {@code SwingWorker} is placed in a waiting queue. * *

- * Note: {@code SwingWorker} is only designed to be executed once. Executing a - * {@code SwingWorker} more than once will not result in invoking the + * Note: {@code SwingWorker} is only designed to be executed once. Executing a {@code SwingWorker} more than once will not result in invoking the * {@code doInBackground} method twice. */ public final void execute() { @@ -559,19 +510,15 @@ public final void execute() { } /** - * Reports a bound property update to any registered listeners. No event is - * fired if {@code old} and {@code new} are equal and non-null. + * Reports a bound property update to any registered listeners. No event is fired if {@code old} and {@code new} are equal and non-null. * *

* This {@code SwingWorker} will be the source for any generated events. * *

- * When called off the Event Dispatch Thread - * {@code PropertyChangeListeners} are notified asynchronously on the Event - * Dispatch Thread. + * When called off the Event Dispatch Thread {@code PropertyChangeListeners} are notified asynchronously on the Event Dispatch Thread. *

- * Note: This is merely a convenience wrapper. All work is delegated to - * {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}. + * Note: This is merely a convenience wrapper. All work is delegated to {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}. * * * @param propertyName @@ -588,13 +535,11 @@ public final void firePropertyChange(String propertyName, Object oldValue, Objec /** * {@inheritDoc} *

- * Note: calling {@code get} on the Event Dispatch Thread blocks - * all events, including repaints, from being processed until this + * Note: calling {@code get} on the Event Dispatch Thread blocks all events, including repaints, from being processed until this * {@code SwingWorker} is complete. * *

- * When you want the {@code SwingWorker} to block on the Event Dispatch - * Thread we recommend that you use a modal dialog. + * When you want the {@code SwingWorker} to block on the Event Dispatch Thread we recommend that you use a modal dialog. * *

* For example: @@ -648,18 +593,14 @@ public final int getProgress() { // Future methods END /** - * Returns the {@code PropertyChangeSupport} for this {@code SwingWorker}. - * This method is used when flexible access to bound properties support is + * Returns the {@code PropertyChangeSupport} for this {@code SwingWorker}. This method is used when flexible access to bound properties support is * needed. *

* This {@code SwingWorker} will be the source for any generated events. * *

- * Note: The returned {@code PropertyChangeSupport} notifies any - * {@code PropertyChangeListener}s asynchronously on the Event Dispatch - * Thread in the event that {@code firePropertyChange} or - * {@code fireIndexedPropertyChange} are called off the Event Dispatch - * Thread. + * Note: The returned {@code PropertyChangeSupport} notifies any {@code PropertyChangeListener}s asynchronously on the Event Dispatch Thread + * in the event that {@code firePropertyChange} or {@code fireIndexedPropertyChange} are called off the Event Dispatch Thread. * * @return {@code PropertyChangeSupport} for this {@code SwingWorker} */ @@ -702,8 +643,7 @@ public final boolean isDone() { // PropertyChangeSupports methods END /** - * Receives data chunks from the {@code publish} method asynchronously on the - * Event Dispatch Thread. + * Receives data chunks from the {@code publish} method asynchronously on the Event Dispatch Thread. * *

* Please refer to the {@link #publish} method for more details. @@ -718,16 +658,12 @@ protected void process(List chunks) { } /** - * Sends data chunks to the {@link #process} method. This method is to be used - * from inside the {@code doInBackground} method to deliver intermediate - * results for processing on the Event Dispatch Thread inside the - * {@code process} method. + * Sends data chunks to the {@link #process} method. This method is to be used from inside the {@code doInBackground} method to deliver intermediate + * results for processing on the Event Dispatch Thread inside the {@code process} method. * *

- * Because the {@code process} method is invoked asynchronously on the - * Event Dispatch Thread multiple invocations to the {@code publish} - * method might occur before the {@code process} method is executed. For - * performance purposes all these invocations are coalesced into one + * Because the {@code process} method is invoked asynchronously on the Event Dispatch Thread multiple invocations to the {@code publish} + * method might occur before the {@code process} method is executed. For performance purposes all these invocations are coalesced into one * invocation with concatenated arguments. * *

@@ -746,10 +682,8 @@ protected void process(List chunks) { * * *

- * Sample Usage. This code snippet loads some tabular data and updates - * {@code DefaultTableModel} with it. Note that it safe to mutate the - * tableModel from inside the {@code process} method because it is invoked on - * the Event Dispatch Thread. + * Sample Usage. This code snippet loads some tabular data and updates {@code DefaultTableModel} with it. Note that it safe to mutate the + * tableModel from inside the {@code process} method because it is invoked on the Event Dispatch Thread. * *

    * class TableSwingWorker extends 
@@ -805,16 +739,12 @@ protected void submit() {
   }
 
   /**
-   * Removes a {@code PropertyChangeListener} from the listener list. This
-   * removes a {@code PropertyChangeListener} that was registered for all
-   * properties. If {@code listener} was added more than once to the same event
-   * source, it will be notified one less time after being removed. If
-   * {@code listener} is {@code null}, or was never added, no exception is
-   * thrown and no action is taken.
+   * Removes a {@code PropertyChangeListener} from the listener list. This removes a {@code PropertyChangeListener} that was registered for all
+   * properties. If {@code listener} was added more than once to the same event source, it will be notified one less time after being removed. If
+   * {@code listener} is {@code null}, or was never added, no exception is thrown and no action is taken.
    * 
    * 

- * Note: This is merely a convenience wrapper. All work is delegated to - * {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}. + * Note: This is merely a convenience wrapper. All work is delegated to {@code PropertyChangeSupport} from {@link #getPropertyChangeSupport}. * * @param listener * the {@code PropertyChangeListener} to be removed @@ -824,8 +754,7 @@ public final void removePropertyChangeListener(PropertyChangeListener listener) } /** - * Sets this {@code Future} to the result of computation unless it has been - * cancelled. + * Sets this {@code Future} to the result of computation unless it has been cancelled. */ @Override public final void run() { @@ -833,16 +762,12 @@ public final void run() { } /** - * Sets the {@code progress} bound property. The value should be from 0 to - * 100. + * Sets the {@code progress} bound property. The value should be from 0 to 100. * *

- * Because {@code PropertyChangeListener}s are notified asynchronously on the - * Event Dispatch Thread multiple invocations to the - * {@code setProgress} method might occur before any - * {@code PropertyChangeListeners} are invoked. For performance purposes all - * these invocations are coalesced into one invocation with the last - * invocation argument only. + * Because {@code PropertyChangeListener}s are notified asynchronously on the Event Dispatch Thread multiple invocations to the + * {@code setProgress} method might occur before any {@code PropertyChangeListeners} are invoked. For performance purposes all these invocations are + * coalesced into one invocation with the last invocation argument only. * *

* For example, the following invocations: @@ -853,8 +778,7 @@ public final void run() { * setProgress(3); *

* - * might result in a single {@code PropertyChangeListener} notification with - * the value {@code 3}. + * might result in a single {@code PropertyChangeListener} notification with the value {@code 3}. * * @param progress * the progress value to set