@@ -42,19 +42,28 @@ This file is part of the iText (R) project.
42
42
*/
43
43
package com .itextpdf .rups .model ;
44
44
45
+ import java .awt .Dialog ;
46
+ import java .awt .GraphicsConfiguration ;
47
+ import java .awt .Insets ;
48
+ import java .awt .Rectangle ;
49
+ import java .awt .Toolkit ;
50
+ import java .awt .Window ;
51
+ import java .awt .event .HierarchyEvent ;
45
52
import javax .swing .JOptionPane ;
46
53
import javax .swing .JScrollPane ;
47
54
import javax .swing .JTextArea ;
48
55
import java .awt .Component ;
49
56
import java .awt .Dimension ;
50
57
import java .io .PrintWriter ;
51
58
import java .io .StringWriter ;
59
+ import javax .swing .SwingUtilities ;
52
60
53
61
/**
54
62
* A utility to display a dialog showing Throwable object
55
63
*/
56
64
public final class ErrorDialogPane {
57
- private static final Dimension DIALOG_PREFERRED_SIZE = new Dimension (300 , 200 );
65
+ private static final int DEFAULT_DOUBLED_MARGIN = 100 ;
66
+ private static final int FALLBACK_MAX_SIZE_DIM = 200 ;
58
67
59
68
private ErrorDialogPane () {
60
69
// do not instantiate
@@ -64,10 +73,73 @@ public static void showErrorDialog(Component parent, Throwable th) {
64
73
final String msg = getTraceString (th );
65
74
final JTextArea textArea = new JTextArea (msg );
66
75
final JScrollPane scrollPane = new JScrollPane (textArea );
67
- scrollPane .setPreferredSize (DIALOG_PREFERRED_SIZE );
76
+ /*
77
+ * Update the dialog, created by JOptionPane, using the HierarchyListener.
78
+ * Taken from https://stackoverflow.com/a/7989417/6564861 and the linked blog post
79
+ * (which was cached in Wayback Machine).
80
+ */
81
+ scrollPane .addHierarchyListener (ErrorDialogPane ::tweakDialogSize );
68
82
JOptionPane .showMessageDialog (parent , scrollPane );
69
83
}
70
84
85
+ private static void tweakDialogSize (HierarchyEvent e ) {
86
+ final Window window = SwingUtilities .getWindowAncestor (e .getComponent ());
87
+ // We are fishing for JOptionPane dialog...
88
+ if (!(window instanceof Dialog )) {
89
+ return ;
90
+ }
91
+ Dialog dialog = (Dialog ) window ;
92
+ /*
93
+ * If dialog was set to resizeable, then this handler was already
94
+ * called for the dialog. So no reason to change sizes again.
95
+ */
96
+ if (dialog .isResizable ()) {
97
+ return ;
98
+ }
99
+ dialog .setResizable (true );
100
+ limitDialogSize (dialog );
101
+ }
102
+
103
+ /**
104
+ * Limits the preferred size of the window based on the linked graphics
105
+ * configuration.
106
+ *
107
+ * @param window Window to update.
108
+ */
109
+ private static void limitDialogSize (Window window ) {
110
+ final GraphicsConfiguration gc = window .getGraphicsConfiguration ();
111
+ if (gc == null ) {
112
+ return ;
113
+ }
114
+ final Rectangle bounds = gc .getBounds ();
115
+ final Insets insets = Toolkit .getDefaultToolkit ().getScreenInsets (gc );
116
+ final int gcMaxWidth = Math .max (
117
+ FALLBACK_MAX_SIZE_DIM ,
118
+ bounds .width - insets .left - insets .right - DEFAULT_DOUBLED_MARGIN
119
+ );
120
+ final int gcMaxHeight = Math .max (
121
+ FALLBACK_MAX_SIZE_DIM ,
122
+ bounds .height - insets .top - insets .bottom - DEFAULT_DOUBLED_MARGIN
123
+ );
124
+ final Dimension currentSize = window .getPreferredSize ();
125
+ boolean sizeModified = false ;
126
+ if (currentSize .width > gcMaxWidth ) {
127
+ currentSize .width = gcMaxWidth ;
128
+ sizeModified = true ;
129
+ }
130
+ if (currentSize .height > gcMaxHeight ) {
131
+ currentSize .height = gcMaxHeight ;
132
+ sizeModified = true ;
133
+ }
134
+ /*
135
+ * We should call setPreferredSize only when we actually change the
136
+ * size. As it might be calculated dynamically, if not set explicitly.
137
+ */
138
+ if (sizeModified ) {
139
+ window .setPreferredSize (currentSize );
140
+ }
141
+ }
142
+
71
143
private static String getTraceString (Throwable th ) {
72
144
final StringWriter sw = new StringWriter ();
73
145
final PrintWriter pw = new PrintWriter (sw );
0 commit comments