/** * Copyright (c) 2014 - 2017 Frank Appel * 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: * Frank Appel - initial API and implementation */ package com.codeaffine.eclipse.swt.layout; import static java.lang.Boolean.valueOf; import static java.lang.Integer.valueOf; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Layout; public class LayoutWrapper extends Layout { private final Layout layout; @FunctionalInterface interface Producer<T> { T produce() throws Exception; } public LayoutWrapper( Layout layout ) { this.layout = layout; } @Override public Point computeSize( Composite composite, int wHint, int hHint, boolean flushCache ) { return runWithExceptionHandling( () -> doComputeSize( composite, wHint, hHint, flushCache ) ); } @Override public void layout( Composite composite, boolean flushCache ) { runWithExceptionHandling( () -> { doLayout( composite, flushCache ); return null; } ); } private Point doComputeSize( Composite composite, int wHint, int hHint, boolean flushCache ) throws Exception { Method method = getDeclaredMethod( "computeSize", Composite.class, int.class, int.class, boolean.class ); return ( Point )method.invoke( layout, composite, valueOf( wHint ), valueOf( hHint ), valueOf( flushCache ) ); } private void doLayout( Composite composite, boolean flushCache ) throws Exception { Method method = getDeclaredMethod( "layout", Composite.class, boolean.class ); method.invoke( layout, composite, valueOf( flushCache ) ); } private static Method getDeclaredMethod( String name, Class<?>... parameterTypes ) throws Exception { Method result = Layout.class.getDeclaredMethod( name, parameterTypes ); result.setAccessible( true ); return result; } private static <T> T runWithExceptionHandling( Producer<T> producer ) { try { return producer.produce(); } catch( InvocationTargetException ite ) { if( ite.getCause() instanceof RuntimeException ) { throw ( RuntimeException )ite.getCause(); } throw new IllegalStateException( ite.getCause() ); } catch( Exception shouldNotHappen ) { throw new IllegalStateException( shouldNotHappen ); } } }