/* 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 2011 Samuel Marshall. */ package com.leafdigital.ui; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import org.w3c.dom.Element; import com.leafdigital.ui.api.*; import com.leafdigital.ui.api.Dialog; import leafchat.core.api.BugException; /** Implementation of dialog */ public class DialogImp extends JDialog { final static int MINWIDTH=WindowImp.MINWIDTH,MINHEIGHT=WindowImp.MINHEIGHT; /** Minimum size for resizing etc. */ private Dimension minSize=new Dimension(MINWIDTH,MINHEIGHT); private UISingleton owner; /** Handles callbacks */ private CallbackHandler ch; /** Offsets for titlebar etc */ private static int widthOffset=-1,heightOffset; private String onClosed=null; DialogImp(UISingleton uis,Object oCallbacks) { super((Frame)null,true); // Null because we don't know yet what parent is, it comes in for show() setResizable(false); owner=uis; ch=new CallbackHandlerImp(oCallbacks); getContentPane().setLayout(new BorderLayout()); addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { if(getWidth()<minSize.width || getHeight()<minSize.height) { setSize( Math.max(minSize.width,getWidth()), Math.max(minSize.height,getHeight())); } } }); setDefaultCloseOperation(DISPOSE_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { if(onClosed!=null) getInterface().getCallbackHandler().callHandleErrors(onClosed); } }); } Dialog getInterface() { return di; } private DialogInterface di=new DialogInterface(); class DialogInterface implements Dialog,InternalWidgetOwner { private Dimension initialSize=null; private boolean shown, created; /** Map of string -> Widget for contained widgets */ private Map<String, Widget> widgetIDs = new HashMap<String, Widget>(); /** Map of string -> ButtonGroup */ private Map<String, ButtonGroup> groups = new HashMap<String, ButtonGroup>(); private InternalWidget rootWidget=null; private HashMap<String, Set<BaseGroup>> arbitraryGroups = new HashMap<String, Set<BaseGroup>>(); @Override public void setTitle(String title) { DialogImp.this.setTitle(title); } @Override public void setInitialSize(int width, int height) { initialSize=new Dimension(width,height); } @Override public void setResizable(boolean resizable) { DialogImp.this.setResizable(resizable); } @Override public void setCloseable(boolean closeable) { DialogImp.this.setDefaultCloseOperation( closeable ? DISPOSE_ON_CLOSE : DO_NOTHING_ON_CLOSE); } @Override public void setMinSize(int minWidth, int minHeight) { if(minWidth < MINWIDTH) minWidth=MINWIDTH; if(minHeight < MINHEIGHT) minHeight=MINHEIGHT; minSize=new Dimension(minWidth,minHeight); } @Override public void show(final WidgetOwner specifiedParent) { if(shown) throw new Error("Cannot show dialog twice."); shown=true; UISingleton.runInSwing(new Runnable() { @Override public void run() { // Set the dialog's size int startW,startH; if(initialSize!=null) { startW=initialSize.width; startH=initialSize.height; } else { if(rootWidget!=null) { if(widthOffset==-1) { ((JComponent)getContentPane()).setPreferredSize(new Dimension(100,100)); pack(); widthOffset=getSize().width-100; heightOffset=getSize().height-100; } startW=rootWidget.getPreferredWidth()+widthOffset; startH=rootWidget.getPreferredHeight(startW)+heightOffset; } else { startW=minSize.width; startH=minSize.height; } } int width=Math.max(startW,minSize.width), height=Math.max(startH,minSize.height); setSize(width,height); // Show window owner.setDialogPosition(DialogImp.this,specifiedParent); setVisible(true); } }); } @Override public void setContents(Widget w) { // Clear IDs widgetIDs.clear(); rootWidget=(InternalWidget)w; rootWidget.setOwner(this); // Just set it within the content panel getContentPane().removeAll(); getContentPane().add(rootWidget.getJComponent(),BorderLayout.CENTER); } @Override public void setContents(Element e) { // Clear IDs widgetIDs.clear(); rootWidget=(InternalWidget)owner.createWidget(e,this); rootWidget.setOwner(this); // Just set it within the content panel getContentPane().removeAll(); getContentPane().add(rootWidget.getJComponent(),BorderLayout.CENTER); } @Override public void close() { UISingleton.runInSwing(new Runnable() { @Override public void run() { DialogImp.this.dispose(); } }); } @Override public Widget getWidget(String id) { Widget w=widgetIDs.get(id); if(w==null) throw new BugException("Widget ID not present: "+id); else return w; } @Override public void setWidgetID(String id,Widget w) { if(widgetIDs.put(id,w)!=null) throw new BugException( "Widget ID not unique: "+id); } @Override public ButtonGroup getButtonGroup(String group) { ButtonGroup bg=groups.get(group); if(bg==null) { bg=new ButtonGroup(); groups.put(group,bg); } return bg; } @Override public RadioButton getGroupSelected(String group) { ButtonGroup bg=getButtonGroup(group); for(Enumeration<AbstractButton> e=bg.getElements();e.hasMoreElements();) { RadioButtonImp.MyRadioButton rb=(RadioButtonImp.MyRadioButton)e.nextElement(); if(rb.isSelected()) return rb.getInterface(); } return null; } @Override public Set<BaseGroup> getArbitraryGroup(String group) { Set<BaseGroup> s = arbitraryGroups.get(group); if(s==null) { s = new HashSet<BaseGroup>(); arbitraryGroups.put(group,s); } return s; } @Override public CallbackHandler getCallbackHandler() { return ch; } @Override public void setOnClosed(String callback) { getCallbackHandler().check(callback); onClosed=callback; } JComponent getPositionReferent() { return (JComponent)getContentPane(); } @Override public boolean isCreated() { return created; } @Override public void markCreated() { created = true; } } }