/* * Bibliothek - DockingFrames * Library built on Java/Swing, allows the user to "drag and drop" * panels containing any Swing-Component the developer likes to add. * * Copyright (C) 2010 Benjamin Sigg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.extension.gui.dock.station; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import bibliothek.gui.DockStation; import bibliothek.gui.Dockable; import bibliothek.gui.dock.ScreenDockStation; import bibliothek.gui.dock.SplitDockStation; import bibliothek.gui.dock.action.ListeningDockAction; import bibliothek.gui.dock.displayer.DisplayerCombinerTarget; import bibliothek.gui.dock.station.Combiner; import bibliothek.gui.dock.station.StationPaint; import bibliothek.gui.dock.station.split.SplitDockPathProperty; import bibliothek.gui.dock.station.split.SplitDockPathProperty.Location; import bibliothek.gui.dock.station.split.SplitNode; import bibliothek.gui.dock.station.support.CombinerSource; import bibliothek.gui.dock.station.support.CombinerTarget; import bibliothek.gui.dock.station.support.Enforcement; import bibliothek.gui.dock.station.support.PlaceholderMap; import bibliothek.gui.dock.themes.basic.BasicCombiner; import bibliothek.util.ClientOnly; /** * This is an alternative implementation of a {@link Combiner}, normally not used by this framework. This * {@link Combiner} creates a {@link SplitDockStation} if the parent station is a {@link ScreenDockStation}. * @author Benjamin Sigg */ @ClientOnly public class SplitCombiner extends BasicCombiner{ public CombinerTarget prepare( CombinerSource source, Enforcement force ){ if( source.isMouseOverTitle() || !(source.getParent() instanceof ScreenDockStation) ){ return super.prepare( source, force ); } Dimension size = source.getSize(); Point position = source.getMousePosition(); if( size == null || position == null ){ return super.prepare( source, force ); } if( isCentered( size.width, size.height, position.x, position.y )){ return super.prepare( source, force ); } boolean topLeft = SplitNode.above( 0, size.height, size.width, 0, position.x, position.y ); boolean topRight = SplitNode.above( 0, 0, size.width, size.height, position.x, position.y ); Location put; if( topLeft && topRight ){ put = Location.TOP; } else if( topLeft && !topRight ){ put = Location.LEFT; } else if( !topLeft && topRight ){ put = Location.RIGHT; } else{ put = Location.BOTTOM; } Dimension newSize = source.getNew().getComponent().getSize(); double oldSpace; double newSpace; double space; if( put == Location.LEFT || put == Location.RIGHT ){ oldSpace = size.width; newSpace = newSize.width; } else{ oldSpace = size.height; newSpace = newSize.height; } if( newSpace < 10 ){ newSpace = 10; } if( newSpace + 10 > oldSpace ){ newSpace = oldSpace - 10; } if( newSpace < 10 ){ space = 0.5; } else{ space = newSpace / oldSpace; } return new Target( source.getParent(), put, space ); } /** * Tells whether the position <code>x/y</code> is centered in <code>width/height</code>. * @param width the width of some area * @param height the height of some area * @param x x-coordinate of a point * @param y y-coordinate of a point * @return <code>true</code> if <code>x/y</code> is centered */ protected boolean isCentered( int width, int height, int x, int y ){ if( x < width / 3 || x > width * 2 / 3 ) return false; if( y < height / 3 || y > height * 2 / 3 ) return false; return true; } public Dockable combine( CombinerSource source, CombinerTarget target ){ if( target instanceof Target ){ DockStation parent = source.getParent(); PlaceholderMap placeholders = source.getPlaceholders(); SplitDockStation split = new SplitDockStation(){ @Override protected ListeningDockAction createFullScreenAction(){ return null; } }; split.setController( parent.getController() ); split.updateTheme(); if( placeholders != null ){ split.setPlaceholders( placeholders ); } split.drop( source.getOld() ); Target splitTarget = (Target)target; SplitDockPathProperty location = new SplitDockPathProperty(); location.add( splitTarget.side, splitTarget.space, -1 ); split.drop( source.getNew(), location ); return split; } else{ return super.combine( source, target ); } } /** * Internal {@link CombinerTarget} of {@link SplitCombiner}, draws markings * at one side of a {@link Dockable}. * @author Benjamin Sigg */ private static class Target implements CombinerTarget{ private DockStation station; private SplitDockPathProperty.Location side; private double space; /** * Creates a new target. * @param station the station associated with this target * @param side the side at which the element will be added * @param space the size of the new element */ public Target( DockStation station, SplitDockPathProperty.Location side, double space ){ this.station = station; this.side = side; this.space = space; } public void paint( Graphics g, Component component, StationPaint paint, Rectangle stationBounds, Rectangle dockableBounds ){ Rectangle destination = new Rectangle( dockableBounds ); switch( side ){ case TOP: destination.height = (int)(destination.height * space); break; case BOTTOM: destination.height = (int)(destination.height * space); destination.y += dockableBounds.height - destination.height; break; case LEFT: destination.width = (int)(destination.width * space); break; case RIGHT: destination.width = (int)(destination.width * space); destination.x += dockableBounds.width - destination.width; } paint.drawInsertion( g, station, dockableBounds, destination ); } public DisplayerCombinerTarget getDisplayerCombination(){ return null; } } }