/* This file is part of leafdigital leafChat. leafChat is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. leafChat 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 General Public License for more details. You should have received a copy of the GNU General Public License along with leafChat. If not, see <http://www.gnu.org/licenses/>. Copyright 2012 Samuel Marshall. */ package com.leafdigital.ui; import java.util.*; import javax.swing.JComponent; import com.leafdigital.ui.api.*; /** * Implements VerticalPanel */ public class VerticalPanelImp extends JComponent { /** Spacing between grid squares */ private int spacing=0; /** Border at edge of grid */ private int border=0; /** Keep record of held components */ private List<InternalWidget> components = new LinkedList<InternalWidget>(); /** Constructor */ VerticalPanelImp() { setLayout(null); } @Override public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); updateLayout(); } /** Move all components to their correct place in new layout */ private void updateLayout() { UISingleton.checkSwing(); // Get available width int iWidth=getWidth()-border*2; int iY=border; // Go through components laying them out synchronized(components) { for(InternalWidget iw : components) { if(!iw.isVisible()) continue; int iWidgetHeight=iw.getPreferredHeight(iWidth); iw.getJComponent().setBounds(border,iY,iWidth,iWidgetHeight); iY+=iWidgetHeight; iY+=spacing; } } repaint(); } /** @return Interface giving limited public access */ VerticalPanel getInterface() { return externalInterface; } /** Interface available to public */ private VerticalPanel externalInterface=new VerticalPanelInterface(); /** Interface available to public */ class VerticalPanelInterface extends BasicWidget implements VerticalPanel,InternalWidget { @Override public int getContentType() { return CONTENT_UNNAMEDSLOTS; } @Override public JComponent getJComponent() { return VerticalPanelImp.this; } @Override public int getPreferredWidth() { // Find largest component width int width=0; synchronized(components) { for(InternalWidget iw : components) { if(!iw.isVisible()) continue; width=Math.max(width,iw.getPreferredWidth()); } } return width+2*border; } @Override public int getPreferredHeight(int width) { if(width==0) return 0; int height=0; synchronized(components) { for(InternalWidget iw : components) { if(!iw.isVisible()) continue; height+=iw.getPreferredHeight(width-2*border); height+=spacing; } } height-=spacing; // Compensate for adding last space return height+2*border; } @Override public void setSpacing(final int spacing) { UISingleton.runInSwing(new Runnable() { @Override public void run() { VerticalPanelImp.this.spacing=spacing; revalidate(); updateLayout(); } }); } @Override public void setBorder(final int border) { UISingleton.runInSwing(new Runnable() { @Override public void run() { VerticalPanelImp.this.border=border; revalidate(); updateLayout(); } }); } @Override public void addXMLChild(String slotName, Widget child) { add(child); } @Override public void add(Widget w) { final InternalWidget iw=(InternalWidget)w; iw.setParent(this); UISingleton.runInSwing(new Runnable() { @Override public void run() { VerticalPanelImp.this.add(iw.getJComponent()); synchronized(components) { components.add(iw); } revalidate(); updateLayout(); } }); } @Override public Widget[] getWidgets() { List<Widget> all = new LinkedList<Widget>(); synchronized(components) { for(InternalWidget w : components) { if(w != null) { all.add(w); } } } return all.toArray(new Widget[all.size()]); } @Override public void remove(Widget w) { final InternalWidget iw=(InternalWidget)w; UISingleton.runInSwing(new Runnable() { @Override public void run() { VerticalPanelImp.this.remove(iw.getJComponent()); synchronized(components) { components.remove(iw); } revalidate(); updateLayout(); } }); } @Override public void removeAll() { UISingleton.runInSwing(new Runnable() { @Override public void run() { InternalWidget[] aiw; synchronized(components) { aiw=components.toArray(new InternalWidget[components.size()]); components.clear(); } for(int i=0;i<aiw.length;i++) { VerticalPanelImp.this.remove(aiw[i].getJComponent()); } revalidate(); updateLayout(); } }); } @Override public void redoLayout() { updateLayout(); super.redoLayout(); } }; }