/* 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.awt.Dimension; import java.util.*; import javax.swing.*; import javax.swing.event.*; import com.leafdigital.ui.api.*; import leafchat.core.api.*; /** * Implements TabPanel. */ public class TabPanelImp extends JTabbedPane implements PageImp.PageTitleOwner { /** Keep record of held components */ private List<InternalWidget> components = new LinkedList<InternalWidget>(); /** Border setting */ private int border; /** Listener called on change */ private String onChange; private boolean disableEvents; private static int widthOffset,heightOffset=-1; /** Constructor */ TabPanelImp() { // Calculate how much size the tab panel bits take up if(heightOffset==-1) { JPanel p=new JPanel(); p.setPreferredSize(new Dimension(100,100)); JTabbedPane tp=new JTabbedPane(); tp.addTab("My tab",p); heightOffset=tp.getPreferredSize().height-100; widthOffset=tp.getPreferredSize().width-100; } addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if(onChange!=null && !disableEvents) { getInterface().getOwner().getCallbackHandler().callHandleErrors(onChange); } } }); } /** @return The interface giving limited public access */ TabPanel getInterface() { return externalInterface; } /** Interface available to public */ private TabPanel externalInterface=new TabPanelInterface(); /** Interface available to public */ class TabPanelInterface extends BasicWidget implements TabPanel,InternalWidget { @Override public int getContentType() { return CONTENT_UNNAMEDSLOTS; } @Override public JComponent getJComponent() { return TabPanelImp.this; } @Override public int getPreferredWidth() { // Find largest component width int iWidth=0; synchronized(components) { for(InternalWidget iw : components) { iWidth=Math.max(iWidth,iw.getPreferredWidth()); } } return iWidth+widthOffset+2*border; } @Override public int getPreferredHeight(int width) { if(width==0) return 0; int height=0; synchronized(components) { for(InternalWidget iw : components) { height=Math.max(height,iw.getPreferredHeight(width-widthOffset-2*border)); } } return height+heightOffset+2*border; } @Override public void setBorder(final int border) { UISingleton.runInSwing(new Runnable() { @Override public void run() { TabPanelImp.this.border=border; TabPanelImp.this.setBorder(BorderFactory.createEmptyBorder( border,border,border,border)); } }); } @Override public void addXMLChild(String slotName, Widget child) { if(!(child instanceof Page)) throw new BugException( "TabPanel <tab> may only contain <Page>"); add((Page)child); } @Override public void add(final Page p) { ((InternalWidget)p).setParent(this); UISingleton.runInSwing(new Runnable() { @Override public void run() { PageImp.PageInterface pi=(PageImp.PageInterface)p; TabPanelImp.this.addTab(p.getTitle(),pi.getJComponent()); pi.informTitleChanges(TabPanelImp.this); synchronized(components) { components.add(pi); } repaint(); } }); } @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() { TabPanelImp.this.remove(iw.getJComponent()); synchronized(components) { components.remove(iw); } repaint(); } }); } @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++) { TabPanelImp.this.remove(aiw[i].getJComponent()); } repaint(); } }); } @Override public void display(String id) throws BugException { Widget w=getOwner().getWidget(id); if(w==null) throw new BugException("Can't find component "+id); try { setSelectedComponent(((InternalWidget)w).getJComponent()); } catch(IllegalArgumentException iae) { throw new BugException("Component "+id+" is not within TabPanel"); } } @Override public String getDisplayed() { java.awt.Component c=getSelectedComponent(); synchronized(components) { for(InternalWidget iw : components) { if(iw.getJComponent()==c) { return iw.getID(); } } } return null; } @Override public void setOnChange(String callback) { getOwner().getCallbackHandler().check(callback); onChange=callback; } } @Override public void pageTitleChanged(Page p) { int iIndex=indexOfComponent(((InternalWidget)p).getJComponent()); if(iIndex!=-1) setTitleAt(iIndex,p.getTitle()); }; }