blob: 9ca89acdc53e76c4dd05fe350a01432c9a2c5c01 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.rt.ui.swing.ext;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import org.eclipse.scout.rt.ui.swing.SwingLayoutUtility;
/**
* Root pane with lazy size validation (minSize, maxSize)
* <p>
* When minSize or maxSize or preferred height is not respected then {@link #reflow()} is called.
* <p>
* Only the dimension that needs resize is changed (width, height).
* <p>
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=363148
*/
public class JRootPaneEx extends JRootPane {
private static final long serialVersionUID = 1L;
private Runnable m_reflowJob;
@Override
protected LayoutManager createRootLayout() {
return new RootLayoutEx();
}
/**
* calling this method causes the root pane to post {@link SwingUtilities#invokeLater(Runnable)} a job that later
* calls {@link #reflow()} on this root pane
*
* @param c
* the component that changed visibility
*/
public void notifyVisibleChanged(Component c) {
if (m_reflowJob == null) {
m_reflowJob = new Runnable() {
@Override
public void run() {
try {
evaluateReflow();
}
finally {
m_reflowJob = null;
}
}
};
SwingUtilities.invokeLater(m_reflowJob);
}
}
protected void evaluateReflow() {
if (getParent() == null || !isVisible() || !isShowing()) {
return;
}
// check minSize and maxSize requirements
Dimension d = getSize();
if (d.width > 0 && d.height > 0) {
Dimension[] sizes = SwingLayoutUtility.getValidatedSizes(JRootPaneEx.this);
Dimension minMaxSize = new Dimension(
Math.min(Math.max(d.width, sizes[0].width), sizes[2].width),
Math.min(Math.max(d.height, sizes[0].height), sizes[2].height)
);
int dw = minMaxSize.width - d.width;
int dh = minMaxSize.height - d.height;
int dwPref = sizes[1].width - d.width;
int dhPref = sizes[1].height - d.height;
//OLD: if (dw != 0 || dh != 0 || dwPref != 0 || dhPref != 0) {
//NEW: only force re-pack when min/max or at least prefHeight is not met, forcing preferred size breaks the bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=363148 and tickets 107768, 106554
if (dw != 0 || dh != 0 || dhPref > 0) {
correctRootPaneSize(dw, dh, dwPref, dhPref);
}
}
}
@Override
public void validate() {
SwingLayoutUtility.invalidateSubtree(this);
super.validate();
}
/**
* @deprecated use {@link #reflow()} instead
* @param widthDelta
* is the width correction (existingWidth+widthDelta=correctWidth) to
* meet min/max sizes
* @param heightDelta
* is the height correction
* (existingHeight+heightDelta=correctHeight) to meet min/max sizes
* @param preferredWidthDelta
* is the width correction (existingWidth+widthDelta=prefWidth) to
* meet preferred size
* @param preferredHeightDelta
* is the height correction (existingHeight+heightDelta=prefHeight)
* to meet preferred size
*/
@Deprecated
protected void correctRootPaneSize(int widthDelta, int heightDelta, int preferredWidthDelta, int preferredHeightDelta) {
reflow();
}
protected void reflow() {
}
protected class RootLayoutEx extends JRootPane.RootLayout {
private static final long serialVersionUID = 1L;
@Override
public Dimension maximumLayoutSize(Container target) {
Dimension rd, mbd;
Insets i = getInsets();
if (menuBar != null && menuBar.isVisible()) {
mbd = menuBar.getMaximumSize();
}
else {
mbd = new Dimension(0, 0);
}
if (contentPane != null) {
rd = contentPane.getMaximumSize();
}
else {
rd = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE - i.top - i.bottom - mbd.height - 1);
}
// fixed bug here, use max (and not min)
return new Dimension(Math.max(rd.width, mbd.width) + i.left + i.right, rd.height + mbd.height + i.top + i.bottom);
}
}
}