001    /* 
002     * Copyright (c) Holger Pfaff - http://pfaff.ws
003     *
004     * This software maybe used for any purpose provided the
005     * above copyright notice is retained. It is supplied as is.
006     * No warranty expressed or implied - Use at your own risk.
007     */
008    
009    import java.util.*;
010    import java.awt.*;
011    import java.awt.event.*;
012    
013    /**
014      * (#)Cal.java
015      * @author   Holger Pfaff
016      * @version  3.2 19-Mar-2004<br><br> 
017      *
018      * A Panel with an optional border, titlestring and helptext that 
019      * can be minimized if desired 
020      */
021    
022    public class BorderPanel extends Caption {
023       
024      /**
025       * helptext for this panel null for none
026       */  
027      protected String       helpText = null;
028    
029      /**
030       * nulllayout is used when minimized
031       */  
032      protected NullLayout nullLayout = new NullLayout();
033    
034      /**
035       * can this panel be minimized ?
036       */  
037      protected boolean   miniMizable = false;
038              
039      /**
040       * mouse over icon ?
041       */  
042      private boolean moi = false;
043    
044      /**
045       * mouse over title ?
046       */  
047      private boolean mot = false;
048      
049      /**
050       * space surrounding the caption
051       */  
052            private Insets captionInsets = new Insets(1,2,1,2);
053    
054      /**
055       * space surrounding the (minimize-) icon
056       */  
057            private Insets iconInsets = new Insets(1,1,1,1);
058            
059      /**
060       * The default contructor creates a regualr panel w/o decoration.
061       */  
062            public BorderPanel() {
063              this(NONE, null);
064            }
065            
066      /**
067       * Create a panel with the specified border type.
068       *
069       * @param   borderType   border type.
070       */  
071            public BorderPanel(int borderType) {
072              this(borderType, null);
073            }
074            
075      /**
076       * Create a panel with the specified title string. 
077       * Bordertype BULK is used per default
078       *
079       * @param   title   Title.
080       */  
081            public BorderPanel(String title) {
082              this(BULK, title);
083            }
084            
085      /**
086       * Create a panel with the specified border type and title string.
087       *
088       * @param   borderType   border type.
089       * @param   title       Title.
090       */  
091            public BorderPanel(int borderType, String title) {
092        super(title);
093        this.borderType  = borderType;
094        this.borderDepth = borderType == NONE ? 0 : 1;
095                    this.iconDist    = 6;
096        this.insets      = new Insets(1,1,1,1);
097        this.innerInsets = new Insets(1,1,1,1);
098        addMouseListener(this);
099        addMouseMotionListener(this);
100            }
101            
102      /**
103       * Set the help text for this panel
104       *
105       * @param   helpText   help text.
106       */  
107      public void setHelptext(String helpText) {
108        this.helpText = helpText;
109      }
110      
111      /**
112       * Get this panels help text
113       */  
114      public String getHelptext() {
115        return helpText;
116      }
117              
118      /**
119       * Set the miniMizable property for this panel
120       *
121       * @param   miniMizable   can this panel be minimized?
122       */  
123      public void setMinimizable(boolean miniMizable) {
124        this.miniMizable = miniMizable;
125      }
126      
127      /**
128       * Get this panels miniMizable property
129       */  
130      public boolean minimizable() {
131        return miniMizable;
132      }
133      
134      /**
135       * Force this panel to a specific state
136       *
137       * @param   m   minimized=true maximized=false
138       */  
139      public void setMini(boolean m) {
140        if(m) {
141          if(mini() == false) {
142            nullLayout.setBaseLayout(getLayout());
143            super.setLayout(nullLayout);
144          }
145        } else {
146          if(mini() == true) {
147            super.setLayout(nullLayout.getBaseLayout());
148          }
149        }
150        //if(getFont() != null) refreshAll();
151        refreshAll();
152      }
153      
154      /**
155       * Get this panels state
156       */  
157      public boolean mini() {
158        return getLayout() instanceof NullLayout;
159      }
160    
161      /**
162       * Overwite setLayout() to be able to save old layout
163       */  
164      public void setLayout(LayoutManager l) {
165        if(mini()) {
166          nullLayout.setBaseLayout(l);
167        } else {
168          super.setLayout(l);
169        }
170      }
171            
172      /**
173       * calculate required sizes for this panel
174       */
175      public Dimension measure() {
176        Dimension d = getLayout() == null ? new Dimension() : getLayout().preferredLayoutSize(this);
177                    int w = getInsets().left + iconDist + measureIcon().width + iconDist + measureCaption().width + getInsets().right;
178                    d.width = Math.max(d.width, w);
179                    return d;
180      }
181    
182      /**
183       * calculate Caption (Title) size including a fix one pixel border left/right two pixel top/bottom
184       */
185      public Dimension measureCaption() {
186              if(titleVisible()) {
187                      Dimension d = super.measureCaption();
188                            d.width += captionInsets.left + captionInsets.right; 
189                            d.height += captionInsets.top + captionInsets.bottom;
190                            return d;
191                    } else {
192                      return new Dimension();
193                    }
194      }
195      
196      /**
197       * calculate Icon size including a fix one pixel border left/right two pixel top/bottom
198       */
199      public Dimension measureIcon() {
200        int h = measureCaption("X", getFont(), getFont(), "").height;
201        return iconVisible() ? new Dimension(h + iconInsets.left + iconInsets.right, h + iconInsets.top + iconInsets.bottom) : new Dimension();
202      }
203    
204      /**
205       * calculate titlehight, if any
206       */
207      public int measureTitleHeight() {
208                    int th = Math.max(measureCaption().height, measureIcon().height);
209        return th == 0 ? 0 : th + insets.top;
210      }
211                    
212      /**
213       * get Insets for this panel. insets + innerInsets + titlehight
214       */
215      public Insets getInsets() {
216              return new Insets(insets.top    + borderDepth + innerInsets.top + measureTitleHeight(),
217                                      insets.left   + borderDepth + innerInsets.left,
218                                                                                            insets.bottom + borderDepth + innerInsets.bottom,
219                                                                                      insets.right  + borderDepth + innerInsets.right);
220            }
221        
222      /**
223       * is title currently visible ?
224       */
225      public boolean titleVisible() {
226        return getLabel() != null && getLabel().length() > 0;
227      }
228      
229      /**
230       * is icon currently visible ?
231       */
232      public boolean iconVisible() {
233        return miniMizable;
234      }
235      
236      /**
237       * calculate title position & size
238       */
239      protected Rectangle getTitleRectangle() {
240              Dimension d = measureCaption();
241                    Rectangle r = new Rectangle();
242                    r.x  = insets.left + iconDist;
243                    r.x += iconVisible() ? measureIcon().width + iconDist : 0;
244                    r.y  = insets.top;
245        r.width  = d.width;
246        r.height = d.height;
247                    return r;
248            }
249                    
250      /**
251       * calculate icon position & size
252       */
253      protected Rectangle getIconRectangle() {
254              Dimension d = measureIcon();
255                    Rectangle r = new Rectangle();
256                    r.x = insets.left + iconDist;
257                    r.y = insets.top;
258        r.width  = d.width;
259        r.height = d.height;
260        return r;
261      }
262      
263      /**
264       * Overwirte paint to do the actual artwork ;-)
265       *
266       * @param   g       Graphics object to use
267       */
268      public void paint(Graphics g) {
269              if(g == null) return;
270                    int th = measureTitleHeight();
271              Rectangle br = getRectangle();
272              Rectangle tr = getTitleRectangle();
273              Rectangle ir = getIconRectangle();
274                    
275        makeBim();
276        paintBackground(big);
277        if(borderType == BULK && th > 0) th = th/2 - borderDepth;
278                    if(borderDepth > 0) paintBorder(big, br.x, br.y + th, br.width - 1, br.height - th - 1);
279              if(titleVisible())    paintCaption(big, tr.x, tr.y, tr.width, tr.height);
280              if(iconVisible())     paintIcon(big, ir.x, ir.y, ir.width, ir.height);
281        paintBim(g);
282      }
283    
284      /**
285       * Paint the Caption (Title)
286       *
287       * @param   g       Graphics object to use
288       * @param   x       x-position of describing rect
289       * @param   y       y-position of describing rect
290       * @param   w       width of describing rect
291       * @param   h       height of describing rect
292       */
293      public void paintCaption(Graphics g, int x, int y, int w, int h) {
294        paintBackground(g, x - 1, y, w - 1 + 1, h - 1);
295              super.paintCaption(g, x + captionInsets.left, y + captionInsets.top, w - captionInsets.left - captionInsets.right, h - captionInsets.top - captionInsets.bottom);
296                    if(mot) drawRectangle(g, dim(getBackground(), -110), x - 1, y, w - 1 + 1, h - 1, 1, 0);
297            }
298        
299      /**
300       * Paint the Icon
301       *
302       * @param   g       Graphics object to use
303       * @param   x       x-position of describing rect
304       * @param   y       y-position of describing rect
305       * @param   w       width of describing rect
306       * @param   h       height of describing rect
307       */
308      public void paintIcon(Graphics g, int x, int y, int w, int h) {
309        paintBackground(g, x + 1, y, w - 3, h - 1);
310        drawTriangle(g, getBackground(), x + 1 + iconInsets.left, y + 1 + iconInsets.top, w - 2 - iconInsets.left - iconInsets.right, h - 2 - iconInsets.top - iconInsets.bottom, 1, RAISED | (mini() ? N : S));
311                    if(moi) drawRectangle(g, dim(getBackground(), -110), x, y, w - 1, h - 1, 1, 0);
312      }
313    
314      /**
315       * implement java.awt.event.MouseListener
316       */
317      public void mouseExited(MouseEvent e) {
318        if(moi || mot) {
319          moi = mot = false;
320          repaint();
321        }
322      }
323      
324      /**
325       * implement java.awt.event.MouseListener
326       */
327      public void mouseMoved(MouseEvent e) {
328        boolean i = getIconRectangle().contains(e.getPoint());
329        boolean t = getTitleRectangle().contains(e.getPoint());
330        if(i != moi || t != mot) {
331          moi = i; mot = t;
332          repaint();
333        }
334      }
335      
336      /**
337       * implement java.awt.event.MouseListener
338       */
339      public void mouseClicked(MouseEvent e) {
340        if(getIconRectangle().contains(e.getPoint())) {
341          setMini(!mini());
342        } else {
343          if(helpText != null) {
344            DialogBox.infoDialog(helpText).show(this); mouseExited(e);
345          }
346        }
347                    repaint();
348      }
349    }