@@ -42,19 +42,28 @@ This file is part of the iText (R) project.
4242 */
4343package com .itextpdf .rups .model ;
4444
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 ;
4552import javax .swing .JOptionPane ;
4653import javax .swing .JScrollPane ;
4754import javax .swing .JTextArea ;
4855import java .awt .Component ;
4956import java .awt .Dimension ;
5057import java .io .PrintWriter ;
5158import java .io .StringWriter ;
59+ import javax .swing .SwingUtilities ;
5260
5361/**
5462 * A utility to display a dialog showing Throwable object
5563 */
5664public 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 ;
5867
5968 private ErrorDialogPane () {
6069 // do not instantiate
@@ -64,10 +73,73 @@ public static void showErrorDialog(Component parent, Throwable th) {
6473 final String msg = getTraceString (th );
6574 final JTextArea textArea = new JTextArea (msg );
6675 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 );
6882 JOptionPane .showMessageDialog (parent , scrollPane );
6983 }
7084
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+
71143 private static String getTraceString (Throwable th ) {
72144 final StringWriter sw = new StringWriter ();
73145 final PrintWriter pw = new PrintWriter (sw );
0 commit comments