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.awt.*;
010    import java.util.*;
011    import java.awt.event.*;
012    import java.applet.*;
013    import java.net.URL;
014     
015    /**
016      * (#)Caption.java
017      * @author   Holger Pfaff
018      * @version  3.2 19-Mar-2004<br><br>
019      *
020      * A caption (label) that can display Awt hypertext
021      *
022      */
023    
024    public class Caption extends Awt {
025    
026      /**
027       *  our contents 
028       */
029      protected String caption = null;
030      
031      /**
032       *  icon layout if any 
033       */
034      protected int iconDist = 0;     // distance between icon and caption
035      protected int iconPos  = NONE;  // icon position NONE LEFT RIGHT of caption
036    
037      /**
038       *  component states (used for implementing classes)
039       */
040      protected boolean active = false;     // show component as active (e.g. button down) ?
041      protected boolean entered = false;    // show component as entered (e.g. surrounding rect) ?
042    
043      /**
044       *  Modes 
045       */
046      protected int mode  = 0;     // drawing modes
047      
048      /**
049       *  is layout invalid ? (needed for recalc of href pos)
050       */
051      protected boolean invalid = true;
052      
053      /**
054       *  list of hrefs in this caption. maps rectangle to string
055       */
056      protected Hashtable hrefs = new Hashtable();
057      
058      /**
059       *  list of hrefs in this caption. maps rectangle to string
060       */
061      protected Rectangle activeRect = null;
062      
063      /**
064       * Constructor for an empty caption
065       */
066      public Caption() {
067        this("");
068      }
069      
070      /**
071       * Standard constructor
072       *
073       * @param   caption   the text
074       */
075      public Caption(String caption) {
076        this(caption, LEFT);
077      }
078      
079      /**
080       * Constructor with additional alignment specification
081       *
082       * @param   caption     the text
083       * @param   mode        the line mode
084       */
085      public Caption(String caption, int mode) {
086        this.caption = caption;
087        this.insets = new Insets(1,1,1,1);
088        this.mode = mode;
089        if(getClass() == Caption.class) {
090          addMouseListener(this);
091          addMouseMotionListener(this);
092        }
093      }
094        
095      /**
096       * set a new caption
097       *
098       * @param   caption     the text
099       */
100      public void setCaption(String c) {
101        if(c == null || caption == null || caption.equals(c) == false) {
102          caption = c;
103          doMeasure();
104          repaint();
105        }
106      }
107      
108      /**
109       * get current caption
110       */
111      public String getCaption() {
112        return caption;
113      }
114      
115      /**
116       * set a new caption (compat with java.awt.Label)
117       *
118       * @param   label     the text
119       */
120      public void setLabel(String l) {
121        setCaption(l);
122      }
123      
124      /**
125       * get current caption (compat with java.awt.Label)
126       */
127      public String getLabel() {
128        return getCaption();
129      }
130      
131      /**
132       * set a new caption (compat with java.awt.Label)
133       *
134       * @param   label     the text
135       */
136      public void setTitle(String l) {
137        setCaption(l);
138      }
139      
140      /**
141       * get current caption (compat with java.awt.Label)
142       */
143      public String getTitle() {
144        return getCaption();
145      }
146    
147      /**
148       * set a new caption (compat with java.awt.TextComponent)
149       *
150       * @param   t     the text
151       */
152      public void setText(String t) {
153        setCaption(t);
154      }
155      
156      /**
157       * get current caption (compat with java.awt.TextComponent)
158       */
159      public String getText() {
160        return getCaption();
161      }
162        
163      /**
164       * set the mode
165       *
166       * @param   m     the mode
167       */
168      public void setMode(int m) {
169        if(mode != m) {
170          mode = m;
171          doMeasure();
172          repaint();
173        }
174      }
175      
176      /**
177       * get current mode
178       */
179      public int getMode() {
180        return mode;
181      }
182    
183      /**
184       * set current activity state
185       *
186       * @param   a     the state
187       */
188      public void setActive(boolean a) {
189        if(active != a) {
190          active = a;
191          repaint();
192        }
193      }
194      
195      /**
196       * get current state
197       */
198      public boolean isActive() {
199        return active;
200      }
201      
202      /**
203       * set current entered state
204       *
205       * @param   e     the state
206       */
207      public void setEntered(boolean e) {
208        if(entered != e) {
209          entered = e;
210          repaint();
211        }
212      }
213      
214      /**
215       * get current state
216       */
217      public boolean isEntered() {
218        return entered;
219      }
220      
221      /**
222       * Overwirte paint to do the actual artwork ;-)
223       *
224       * @param   g       Graphics object to use
225       */
226      public void paint(Graphics g) {
227        makeBim();
228        paintBackground(big);
229        
230        int btype = borderType;
231        if(borderType == RAISED && active) {
232          borderType = SUNKEN;
233        }
234        super.paint(big);
235        borderType = btype;
236            
237        if(entered && !active) {
238          Rectangle br = getBorderRectangle();
239          drawRectangle(big, dim(getBackground(), -90), br.x, br.y, br.width - 1, br.height - 1, 1, 0);
240        }
241        
242        Rectangle ir = getInnerRectangle();
243        Dimension id = measureIcon();
244        Dimension cd = measureCaption();
245    
246        if(active) {
247          ir.x++; ir.y++;
248        }
249            
250        paintCaption(big, iconPos == LEFT  ? ir.x + id.width + iconDist : ir.x, ir.y, ir.width - id.width - iconDist, cd.height);
251           paintIcon(big, iconPos == RIGHT && cd.width > 0 ? ir.x + ir.width - id.width : ir.x, ir.y, id.width, id.height);
252        
253        paintBim(g);
254        
255        invalid = false;
256      }
257      
258      /**
259       * Paint the Caption (Title)
260       *
261       * @param   g       Graphics object to use
262       * @param   x       x-position of describing rect
263       * @param   y       y-position of describing rect
264       * @param   w       width of describing rect
265       * @param   h       height of describing rect
266       */
267      public void paintCaption(Graphics g, int x, int y, int w, int h) {
268        drawCaption(g, isEnabled() ? getForeground() : getBackground(), getFont(), caption, x, y, w, h, isEnabled() ? mode : mode | Awt.SUNKEN, "\n", this);
269      }
270      
271      /**
272       * Paint the Icon
273       *
274       * @param   g       Graphics object to use
275       * @param   x       x-position of describing rect
276       * @param   y       y-position of describing rect
277       * @param   w       width of describing rect
278       * @param   h       height of describing rect
279       */
280      public void paintIcon(Graphics g, int x, int y, int w, int h) {
281      }
282      
283      /**
284       * calculate Caption (Title) size including a fix one pixel border left/right two pixel top/bottom
285       */
286      public Dimension measureCaption() {
287        return measureCaption(caption, getFont(), getFont(), "\n");
288      }
289      
290      /**
291       * calculate Icon size - intended as a placeholder for implementing classes
292       */
293      public Dimension measureIcon() {
294        return new Dimension();
295      }
296    
297      /**
298       * calculate required sizes
299       */
300      public Dimension measure() {
301        Dimension bd = super.measure();
302        Dimension cd = measureCaption();
303        Dimension id = measureIcon();
304        bd.width  += cd.width > 0 ? cd.width + iconDist + id.width : id.width;
305        bd.height += Math.max(cd.height, id.height);
306        return bd;
307      }
308      
309      /**
310       * Overwrite Awt.invalidate()
311       */
312      public void invalidate() {
313        hrefs.clear();
314        invalid = true;
315        super.invalidate();
316      }
317      
318      /**
319       * Overwrite Awt.doHref()
320       */
321      public void doHref(String s, int x, int y, int w, int h) {
322        if(invalid) {
323          hrefs.put(new Rectangle(x, y, w, h), s);
324        }
325      }
326      
327      /**
328       * get current Hyper reference if any
329       */
330      public String getHref() {
331        return activeRect == null ? null : exHref((String) hrefs.get(activeRect));
332      }
333          
334      /**
335       * implement java.awt.event.MouseListener
336       */
337      public void mousePressed(MouseEvent e) {
338        if(activeRect != null) {
339          try {
340            getAppletContext(this).showDocument(new URL(getHref()), "_blank");
341                            } catch(Exception x) {
342            Awt.error("Only supported in applet mode", this);
343          }
344        }
345      }
346    
347      /**
348       * implement java.awt.event.MouseListener
349       */
350      public void mouseExited(MouseEvent e) {
351        mouseMoved(e);
352      }
353      
354      /**
355       * implement java.awt.event.MouseListener
356       */
357      public void mouseMoved(MouseEvent e) {
358        for(Enumeration enum = hrefs.keys() ; enum.hasMoreElements() ;) {
359          Rectangle r = (Rectangle) enum.nextElement();
360          if(r.contains(e.getPoint())) {
361            if(activeRect == null || activeRect.equals(r) == false) {
362              setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
363              activeRect = r;
364            }
365            return;
366          }
367        }
368        if(activeRect != null) {
369          activeRect = null;
370          setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
371        }
372      }
373    }