Skip to content

Commit 31eaa6c

Browse files
author
kdgregory
committed
copy selected classes from net.sf.swinglib
1 parent 75b57b8 commit 31eaa6c

File tree

8 files changed

+1210
-3
lines changed

8 files changed

+1210
-3
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
<groupId>net.sf.kdgcommons</groupId>
1212
<artifactId>kdgcommons</artifactId>
13-
<version>1.0.15-SNAPSHOT</version>
13+
<version>1.1.0-SNAPSHOT</version>
1414

1515
<name>KDG Commons</name>
1616
<packaging>jar</packaging>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright Keith D Gregory
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package net.sf.kdgcommons.swing;
16+
17+
import javax.swing.SwingUtilities;
18+
19+
20+
/**
21+
* A base class for implementing operations that need to run on their own thread
22+
* and report back to the event thread. Unlike Sun's <code>SwingWorker</code>
23+
* class, this object does not spawn its own thread. Instead, it must be passed
24+
* to a program-created thread, or better, a threadpool.
25+
* <p>
26+
* To use, subclass and pass an instance to your background thread(pool).
27+
* <p>
28+
* You must implement at least the {@link #performOperation} method, which is
29+
* executed on the operation thread. This method may return a single object,
30+
* or throw any exception type. Depending on how it completes (return/throw),
31+
* one of {@link #onSuccess}, {@link #onFailure} will then be executed on the
32+
* event thread.
33+
*
34+
* @since 1.1.0
35+
**/
36+
37+
public abstract class AsynchronousOperation<T>
38+
implements Runnable
39+
{
40+
public final void run()
41+
{
42+
try
43+
{
44+
final T result = performOperation();
45+
SwingUtilities.invokeLater(new Runnable()
46+
{
47+
public void run()
48+
{
49+
onComplete();
50+
onSuccess(result);
51+
}
52+
});
53+
}
54+
catch (final Throwable e)
55+
{
56+
SwingUtilities.invokeLater(new Runnable()
57+
{
58+
public void run()
59+
{
60+
onComplete();
61+
onFailure(e);
62+
}
63+
});
64+
}
65+
}
66+
67+
68+
/**
69+
* The concrete class implements this method, which is executed on the
70+
* non-event thread. It is permitted to return a value that is then passed
71+
* to the code running on the event thread. It is also permitted to throw
72+
* any exception type.
73+
*/
74+
protected abstract T performOperation()
75+
throws Exception;
76+
77+
78+
/**
79+
* This method is invoked on the event thread when the operation completes,
80+
* <em>regardless of whether it succeeded or failed</em>. It exists so that
81+
* subclasses can manage user feedback (such as resetting a busy cursor).
82+
*/
83+
protected void onComplete()
84+
{
85+
// default implementation does nothing
86+
}
87+
88+
89+
/**
90+
* This method is invoked on the event thread after a successful call to
91+
* <code>performOperation()</code>. Application code typically overrides
92+
* to do something with that result.
93+
*/
94+
protected void onSuccess(T result)
95+
{
96+
// default implementation does nothing
97+
}
98+
99+
100+
/**
101+
* This method is invoked on the event thread if <code>performOperation()
102+
* </code> threw an exception. Application code typically overrides
103+
* to do something with that exception.
104+
*/
105+
protected void onFailure(Throwable e)
106+
{
107+
throw new RuntimeException(e);
108+
}
109+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright Keith D Gregory
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package net.sf.kdgcommons.swing;
16+
17+
import java.awt.Toolkit;
18+
import java.awt.datatransfer.Clipboard;
19+
import java.awt.datatransfer.ClipboardOwner;
20+
import java.awt.datatransfer.DataFlavor;
21+
import java.awt.datatransfer.Transferable;
22+
import java.awt.datatransfer.UnsupportedFlavorException;
23+
import java.io.IOException;
24+
25+
26+
/**
27+
* Provides a simple mechanism for interacting with the system clipboard,
28+
* where you want to copy/paste a restricted set of data types and don't
29+
* want to hook up with a component. Particularly useful for application-
30+
* level actions.
31+
*
32+
* @since 1.1.0
33+
*/
34+
public class ClipManager
35+
{
36+
/**
37+
* Puts the specified string on the system clipboard.
38+
*/
39+
public static void putString(String str)
40+
{
41+
Toolkit.getDefaultToolkit()
42+
.getSystemClipboard()
43+
.setContents(new StringClip(str), new ClipCallback());
44+
}
45+
46+
47+
//----------------------------------------------------------------------------
48+
// Internals
49+
//----------------------------------------------------------------------------
50+
51+
/**
52+
* An object that's notified when the clipboard contents changes. We
53+
* don't really care about that notification, but the clipboard requires
54+
* a callback.
55+
*/
56+
private static class ClipCallback
57+
implements ClipboardOwner
58+
{
59+
public void lostOwnership(Clipboard clipboard, Transferable contents)
60+
{
61+
// nothing happening here
62+
}
63+
}
64+
65+
66+
/**
67+
* Used to package a string for the clipboard.
68+
*/
69+
private static class StringClip
70+
implements Transferable
71+
{
72+
private String _str;
73+
private DataFlavor _myFlavor;
74+
75+
public StringClip(String str)
76+
{
77+
_str = str;
78+
_myFlavor = DataFlavor.stringFlavor;
79+
}
80+
81+
public Object getTransferData(DataFlavor flavor)
82+
throws UnsupportedFlavorException, IOException
83+
{
84+
if (!flavor.equals(_myFlavor))
85+
return null;
86+
87+
return _str;
88+
}
89+
90+
public DataFlavor[] getTransferDataFlavors()
91+
{
92+
return new DataFlavor[] { _myFlavor };
93+
}
94+
95+
public boolean isDataFlavorSupported(DataFlavor flavor)
96+
{
97+
return flavor.equals(_myFlavor);
98+
}
99+
}
100+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright Keith D Gregory
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package net.sf.kdgcommons.swing;
16+
17+
import java.awt.Dimension;
18+
import java.awt.Rectangle;
19+
import java.awt.Toolkit;
20+
import java.awt.Window;
21+
22+
23+
/**
24+
* A collection of static utility methods for Swing apps.
25+
*
26+
* @since 1.1.0
27+
*/
28+
public class SwingUtil
29+
{
30+
/**
31+
* Centers the passed window (dialog or frame) on the screen and makes
32+
* it visible. This is typically used to display the main window for
33+
* an application.
34+
*/
35+
public static void centerAndShow(Window window)
36+
{
37+
center(window);
38+
window.setVisible(true);
39+
}
40+
41+
42+
/**
43+
* Centers the passed window (dialog or frame) within the second window
44+
* and makes it visible. This is typically used to display a dialog.
45+
* <p>
46+
* The second window may be null, in which case the first is centered within
47+
* the screen. This is a convenience for ownerless dialogs.
48+
*/
49+
public static void centerAndShow(Window window, Window inWindow)
50+
{
51+
center(window, inWindow);
52+
window.setVisible(true);
53+
}
54+
55+
56+
/**
57+
* Updates the passed window's position to center it with respect to the
58+
* screen. May be called before or after the window is made visible (but
59+
* remember to call <code>pack()</code> first!).
60+
* <p>
61+
* Deals with multi-monitor setups via the following hack: if the screen
62+
* size reported by the default toolkit has a width:height ration > 2:1,
63+
* then the width is divided by 2. This works well for 1, 2, or 3 screen
64+
* desktops: the window will appear in the left screen of a 2-screen
65+
* setup, in the middle of a 3-screen setup.
66+
* <p>
67+
* If the window is larger than the screen size, it's positioned at the
68+
* top-left corner. Hopefully the user will be able to shrink it.
69+
*/
70+
public static void center(Window window)
71+
{
72+
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
73+
int width = screenSize.width;
74+
int height = screenSize.height;
75+
if (width > height * 2)
76+
width /= 2;
77+
78+
center(window, new Rectangle(0, 0, width, height), false);
79+
}
80+
81+
82+
/**
83+
* Updates the first window's position to center it with respect to the
84+
* second window. If the first window is larger than the second, it will
85+
* be offset to the top/left as needed, but not exceeding the bounds of
86+
* the screen.
87+
* <p>
88+
* The second window may be null, in which case the first is centered within
89+
* the screen. This is a convenience for ownerless dialogs.
90+
*/
91+
public static void center(Window window, Window inWindow)
92+
{
93+
if (inWindow == null)
94+
center(window);
95+
else
96+
center(window, inWindow.getBounds(), true);
97+
}
98+
99+
100+
/**
101+
* Centers a window within a specified space. If the window is larger than
102+
* the width/height of the space, it may optionally overflow: its X and Y
103+
* will be less than those passed. However, it is not allowed to overflow
104+
* to negative coordinates.
105+
*/
106+
private static void center(Window window, Rectangle bounds, boolean allowOverflow)
107+
{
108+
Dimension windowSize = window.getSize();
109+
110+
int offsetX = (bounds.width - windowSize.width) / 2;
111+
if ((offsetX < 0) && !allowOverflow)
112+
offsetX = 0;
113+
114+
int x = bounds.x + offsetX;
115+
if (x < 0)
116+
x = 0;
117+
118+
int offsetY = (bounds.height - windowSize.height) / 2;
119+
if ((offsetY < 0) && !allowOverflow)
120+
offsetY = 0;
121+
122+
int y = bounds.y + offsetY;
123+
if (y < 0)
124+
y = 0;
125+
126+
window.setLocation(x, y);
127+
}
128+
}

0 commit comments

Comments
 (0)