All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.metawidget.swt.layout.MigLayout Maven / Gradle / Ivy

The newest version!
// Metawidget
//
// For historical reasons, this file is licensed under the LGPL
// (http://www.gnu.org/licenses/lgpl-2.1.html).
//
// Most other files in Metawidget are licensed under both the
// LGPL/EPL and a commercial license. See http://metawidget.org
// for details.

package org.metawidget.swt.layout;

import static org.metawidget.inspector.InspectionResultConstants.*;

import java.util.Map;

import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.metawidget.layout.iface.AdvancedLayout;
import org.metawidget.swt.Facet;
import org.metawidget.swt.Stub;
import org.metawidget.swt.SwtMetawidget;
import org.metawidget.util.WidgetBuilderUtils;
import org.metawidget.util.simple.SimpleLayoutUtils;
import org.metawidget.util.simple.StringUtils;

/**
 * Layout to arrange widgets using net.miginfocom.swing.MigLayout.
 * 

* Widgets are arranged in a table, with one column for labels and another for the widget. * * @author Stefan Ackerman */ public class MigLayout implements AdvancedLayout { // // Private members // private final int mNumberOfColumns; private final boolean mDebugMode; // // Constructor // public MigLayout() { this( new MigLayoutConfig() ); } public MigLayout( MigLayoutConfig config ) { mNumberOfColumns = config.getNumberOfColumns(); mDebugMode = config.isDebugMode(); } // // Public methods // public void onStartBuild( SwtMetawidget metawidget ) { // Do nothing } public void startContainerLayout( Composite container, SwtMetawidget metawidget ) { container.setData( MigLayout.class.getName(), null ); State state = getState( container ); // The entire layout should fill both horizontally and vertically, // with no insets. This allows us to be properly nested, as well as // embedded within existing UIs, without alignment problems LC layoutConstraints = new LC().insets( "0" ); // Debug Info (draws the red and blue lines) if ( mDebugMode ) { layoutConstraints.debug( 500 ); } // Create the Layout // // Note: we don't use column/row constraints, because we don't know // what the controls will be in advance. Rather, we use 'cell' and 'push' org.eclipse.swt.widgets.Layout layout = new net.miginfocom.swt.MigLayout( layoutConstraints ); container.setLayout( layout ); // Calculate default label inset // // We top align all our labels, not just those belonging to 'tall' controls, // so that tall controls, regular controls and nested Metawidget controls all line up. // However, we still want the Labels to be middle aligned for one-line controls (such as // Text boxes), so we top inset them a bit state.defaultLabelVerticalPadding = new GC( container ).getFontMetrics().getLeading(); } public void layoutWidget( Control control, String elementName, Map attributes, Composite container, SwtMetawidget metawidget ) { // Do not render empty stubs if ( control instanceof Stub && ( (Stub) control ).getChildren().length == 0 ) { // Must 'CC.setHideMode', because already added to Composite CC controlConstraints = new CC(); controlConstraints.setHideMode( 3 ); control.setLayoutData( controlConstraints ); control.setVisible( false ); return; } // Special support for large controls State state = getState( container ); boolean spanAllColumns = control instanceof SwtMetawidget || SimpleLayoutUtils.isSpanAllColumns( attributes ); if ( spanAllColumns && state.currentColumn > 0 ) { state.currentColumn = 0; state.currentRow++; } // Layout a label... String labelText = null; if ( attributes != null ) { labelText = metawidget.getLabelString( attributes ); } layoutBeforeChild( control, labelText, elementName, attributes, container, metawidget ); // ...and layout the control CC controlConstraints = new CC(); if ( labelText != null ) { controlConstraints.cell( ( state.currentColumn * 2 ) + 1, state.currentRow ); } else { controlConstraints.cell( state.currentColumn * 2, state.currentRow ); controlConstraints.spanX( 2 ); } controlConstraints.pushX( 1f ).growX(); if ( spanAllColumns ) { controlConstraints.spanX(); state.currentColumn = mNumberOfColumns; } controlConstraints.alignY( "top" ); // Assume large controls should grow vertically if ( willFillVertically( control, attributes ) ) { controlConstraints.pushY( 1f ).growY(); } // Add it control.setLayoutData( controlConstraints ); state.currentColumn++; if ( state.currentColumn >= mNumberOfColumns ) { state.currentColumn = 0; state.currentRow++; } } public void endContainerLayout( Composite container, SwtMetawidget metawidget ) { // Do nothing } public void onEndBuild( SwtMetawidget metawidget ) { // Buttons Facet buttonsFacet = metawidget.getFacet( "buttons" ); if ( buttonsFacet != null ) { State state = getState( metawidget ); if ( state.currentColumn > 0 ) { state.currentColumn = 0; state.currentRow++; } buttonsFacet.setLayoutData( new CC().cell( 0, state.currentRow ).spanX().growX() ); buttonsFacet.moveBelow( null ); } } // // Protected methods // protected String layoutBeforeChild( Control control, String labelText, String elementName, Map attributes, Control container, SwtMetawidget metawidget ) { State state = getState( (Composite) container ); // Add label if ( SimpleLayoutUtils.needsLabel( labelText, elementName ) ) { Label label = new Label( (Composite) container, SWT.None ); // Required if ( attributes != null && TRUE.equals( attributes.get( REQUIRED ) ) && !WidgetBuilderUtils.isReadOnly( attributes ) && !metawidget.isReadOnly() ) { label.setText( labelText + "*" + StringUtils.SEPARATOR_COLON ); } else { label.setText( labelText + StringUtils.SEPARATOR_COLON ); } CC labelConstraints = new CC(); labelConstraints.cell( state.currentColumn * 2, state.currentRow ); labelConstraints.growX(); // Top align all labels, not just those belonging to 'tall' controls, // so that tall controls, regular controls and nested Metawidget // controls all line up labelConstraints.alignY( "top" ); // Apply some vertical padding so the label lines up with the control nicely labelConstraints.pad( state.defaultLabelVerticalPadding, 0, state.defaultLabelVerticalPadding, 0 ); // Add it label.setLayoutData( labelConstraints ); label.moveAbove( control ); } return labelText; } /** * @param control * control that may fill vertically */ protected boolean willFillVertically( Control control, Map attributes ) { if ( attributes != null && TRUE.equals( attributes.get( LARGE ) ) ) { return true; } return false; } // // Private methods // private State getState( Composite container ) { State state = (State) container.getData( MigLayout.class.getName() ); if ( state == null ) { state = new State(); container.setData( MigLayout.class.getName(), state ); } return state; } // // Inner class // /** * Simple, lightweight structure for saving state. */ /* package private */static class State { /* package private */int currentColumn; /* package private */int currentRow; /* package private */int defaultLabelVerticalPadding; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy