Skip to content

Commit

Permalink
copy selected classes from net.sf.swinglib
Browse files Browse the repository at this point in the history
  • Loading branch information
kdgregory committed Feb 28, 2015
1 parent 75b57b8 commit 31eaa6c
Show file tree
Hide file tree
Showing 8 changed files with 1,210 additions and 3 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<groupId>net.sf.kdgcommons</groupId>
<artifactId>kdgcommons</artifactId>
<version>1.0.15-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>

<name>KDG Commons</name>
<packaging>jar</packaging>
Expand Down
109 changes: 109 additions & 0 deletions src/main/java/net/sf/kdgcommons/swing/AsynchronousOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright Keith D Gregory
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package net.sf.kdgcommons.swing;

import javax.swing.SwingUtilities;


/**
* A base class for implementing operations that need to run on their own thread
* and report back to the event thread. Unlike Sun's <code>SwingWorker</code>
* class, this object does not spawn its own thread. Instead, it must be passed
* to a program-created thread, or better, a threadpool.
* <p>
* To use, subclass and pass an instance to your background thread(pool).
* <p>
* You must implement at least the {@link #performOperation} method, which is
* executed on the operation thread. This method may return a single object,
* or throw any exception type. Depending on how it completes (return/throw),
* one of {@link #onSuccess}, {@link #onFailure} will then be executed on the
* event thread.
*
* @since 1.1.0
**/

public abstract class AsynchronousOperation<T>
implements Runnable
{
public final void run()
{
try
{
final T result = performOperation();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
onComplete();
onSuccess(result);
}
});
}
catch (final Throwable e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
onComplete();
onFailure(e);
}
});
}
}


/**
* The concrete class implements this method, which is executed on the
* non-event thread. It is permitted to return a value that is then passed
* to the code running on the event thread. It is also permitted to throw
* any exception type.
*/
protected abstract T performOperation()
throws Exception;


/**
* This method is invoked on the event thread when the operation completes,
* <em>regardless of whether it succeeded or failed</em>. It exists so that
* subclasses can manage user feedback (such as resetting a busy cursor).
*/
protected void onComplete()
{
// default implementation does nothing
}


/**
* This method is invoked on the event thread after a successful call to
* <code>performOperation()</code>. Application code typically overrides
* to do something with that result.
*/
protected void onSuccess(T result)
{
// default implementation does nothing
}


/**
* This method is invoked on the event thread if <code>performOperation()
* </code> threw an exception. Application code typically overrides
* to do something with that exception.
*/
protected void onFailure(Throwable e)
{
throw new RuntimeException(e);
}
}
100 changes: 100 additions & 0 deletions src/main/java/net/sf/kdgcommons/swing/ClipManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright Keith D Gregory
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package net.sf.kdgcommons.swing;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;


/**
* Provides a simple mechanism for interacting with the system clipboard,
* where you want to copy/paste a restricted set of data types and don't
* want to hook up with a component. Particularly useful for application-
* level actions.
*
* @since 1.1.0
*/
public class ClipManager
{
/**
* Puts the specified string on the system clipboard.
*/
public static void putString(String str)
{
Toolkit.getDefaultToolkit()
.getSystemClipboard()
.setContents(new StringClip(str), new ClipCallback());
}


//----------------------------------------------------------------------------
// Internals
//----------------------------------------------------------------------------

/**
* An object that's notified when the clipboard contents changes. We
* don't really care about that notification, but the clipboard requires
* a callback.
*/
private static class ClipCallback
implements ClipboardOwner
{
public void lostOwnership(Clipboard clipboard, Transferable contents)
{
// nothing happening here
}
}


/**
* Used to package a string for the clipboard.
*/
private static class StringClip
implements Transferable
{
private String _str;
private DataFlavor _myFlavor;

public StringClip(String str)
{
_str = str;
_myFlavor = DataFlavor.stringFlavor;
}

public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException
{
if (!flavor.equals(_myFlavor))
return null;

return _str;
}

public DataFlavor[] getTransferDataFlavors()
{
return new DataFlavor[] { _myFlavor };
}

public boolean isDataFlavorSupported(DataFlavor flavor)
{
return flavor.equals(_myFlavor);
}
}
}
128 changes: 128 additions & 0 deletions src/main/java/net/sf/kdgcommons/swing/SwingUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright Keith D Gregory
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package net.sf.kdgcommons.swing;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;


/**
* A collection of static utility methods for Swing apps.
*
* @since 1.1.0
*/
public class SwingUtil
{
/**
* Centers the passed window (dialog or frame) on the screen and makes
* it visible. This is typically used to display the main window for
* an application.
*/
public static void centerAndShow(Window window)
{
center(window);
window.setVisible(true);
}


/**
* Centers the passed window (dialog or frame) within the second window
* and makes it visible. This is typically used to display a dialog.
* <p>
* The second window may be null, in which case the first is centered within
* the screen. This is a convenience for ownerless dialogs.
*/
public static void centerAndShow(Window window, Window inWindow)
{
center(window, inWindow);
window.setVisible(true);
}


/**
* Updates the passed window's position to center it with respect to the
* screen. May be called before or after the window is made visible (but
* remember to call <code>pack()</code> first!).
* <p>
* Deals with multi-monitor setups via the following hack: if the screen
* size reported by the default toolkit has a width:height ration > 2:1,
* then the width is divided by 2. This works well for 1, 2, or 3 screen
* desktops: the window will appear in the left screen of a 2-screen
* setup, in the middle of a 3-screen setup.
* <p>
* If the window is larger than the screen size, it's positioned at the
* top-left corner. Hopefully the user will be able to shrink it.
*/
public static void center(Window window)
{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = screenSize.width;
int height = screenSize.height;
if (width > height * 2)
width /= 2;

center(window, new Rectangle(0, 0, width, height), false);
}


/**
* Updates the first window's position to center it with respect to the
* second window. If the first window is larger than the second, it will
* be offset to the top/left as needed, but not exceeding the bounds of
* the screen.
* <p>
* The second window may be null, in which case the first is centered within
* the screen. This is a convenience for ownerless dialogs.
*/
public static void center(Window window, Window inWindow)
{
if (inWindow == null)
center(window);
else
center(window, inWindow.getBounds(), true);
}


/**
* Centers a window within a specified space. If the window is larger than
* the width/height of the space, it may optionally overflow: its X and Y
* will be less than those passed. However, it is not allowed to overflow
* to negative coordinates.
*/
private static void center(Window window, Rectangle bounds, boolean allowOverflow)
{
Dimension windowSize = window.getSize();

int offsetX = (bounds.width - windowSize.width) / 2;
if ((offsetX < 0) && !allowOverflow)
offsetX = 0;

int x = bounds.x + offsetX;
if (x < 0)
x = 0;

int offsetY = (bounds.height - windowSize.height) / 2;
if ((offsetY < 0) && !allowOverflow)
offsetY = 0;

int y = bounds.y + offsetY;
if (y < 0)
y = 0;

window.setLocation(x, y);
}
}
Loading

0 comments on commit 31eaa6c

Please sign in to comment.