home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / LIB / BUTTON.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  17.3 KB  |  603 lines

  1. package sub_arctic.lib;
  2.  
  3. import sub_arctic.input.event;
  4. import sub_arctic.input.callback_object;
  5. import sub_arctic.input.inout_draggable;
  6. import sub_arctic.input.pressable;
  7.  
  8. import sub_arctic.output.color_pair;
  9. import sub_arctic.output.loaded_image;
  10. import sub_arctic.output.drawable;
  11. import sub_arctic.output.style;
  12. import sub_arctic.output.style_manager;
  13.  
  14. import sub_arctic.lib.sub_arctic_error;
  15.  
  16. import java.awt.Point;
  17. import java.awt.Dimension;
  18. import java.awt.Image;
  19. import java.awt.Font;
  20. import java.awt.FontMetrics;
  21. import java.awt.Color;
  22.  
  23. /**
  24.  * This class implements a button in the current style. By default, buttons
  25.  * are not resizable, they have an intrinsic size. You can use the method
  26.  * set_autosize(false) if you desire the button to be resizable to any size.
  27.  * 
  28.  * @author Scott Hudson 
  29.  */
  30. public class button extends multi_button implements inout_draggable,pressable {
  31.  
  32.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  33.  
  34.   /** 
  35.    * Constructor where we expect you to position the object
  36.    * with constraints. The image set given here must contain either one or 
  37.    * two images.  The one at index 0 will be used for normal appearance, and 
  38.    * the one at index 1 (if any) will be used for highlight when the button 
  39.    * is being "depressed". 
  40.    *
  41.    * @param loaded_image[]  look     the two images to display for this button.
  42.    * @param callback_object call_obj the object to run the callbacks on.
  43.    */
  44.   public button(
  45.     loaded_image[]   look, 
  46.     callback_object  call_obj) 
  47. {
  48.       super(0,0,null,null,call_obj);
  49.  
  50.       /* make sure the image set is usable */
  51.       if (look == null || look.length == 0 || look.length > 2)
  52.     throw new sub_arctic_error("Unusable image set passed to button()");
  53.  
  54.       /* if we only have one image, put in a second duplicate entry */
  55.       if (look.length == 1)
  56.     {
  57.       loaded_image[] lk = new loaded_image[2];
  58.       lk[0] = look[0];
  59.       lk[1] = look[1];
  60.       look = lk;
  61.     }
  62.  
  63.       /* set the stuff up with the parent */
  64.       set_looks(look,null);
  65.  
  66.  
  67.       /* calculate correct initial size */
  68.       calc_size();
  69.     }
  70.  
  71.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  72.  
  73.   /** 
  74.    * Full constructor.  The image set given here must contain either one or 
  75.    * two images.  The one at index 0 will be used for normal appearance, and 
  76.    * the one at index 1 (if any) will be used for highlight when the button 
  77.    * is being "depressed". 
  78.    * 
  79.    * @param int             x        the x position of the interactor.
  80.    * @param int             y        the y position of the interactor.
  81.    * @param loaded_image[]  look     the two images to display for this button.
  82.    * @param callback_object call_obj the object to run the callbacks on.
  83.    */
  84.   public button(
  85.     int              x,
  86.     int              y,
  87.     loaded_image[]   look, 
  88.     callback_object  call_obj) 
  89. {
  90.       super(x,y,null,null,call_obj);
  91.  
  92.       /* make sure the image set is usable */
  93.       if (look == null || look.length == 0 || look.length > 2)
  94.     throw new sub_arctic_error("Unusable image set passed to button()");
  95.  
  96.       /* if we only have one image, put in a second duplicate entry */
  97.       if (look.length == 1)
  98.     {
  99.       loaded_image[] lk = new loaded_image[2];
  100.       lk[0] = look[0];
  101.       lk[1] = look[1];
  102.       look = lk;
  103.     }
  104.  
  105.       set_looks(look,null);
  106.  
  107.       /* calculate correct initial size */
  108.       calc_size();
  109.     }
  110.  
  111.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  112.  
  113.   /** 
  114.    * Constructor based on a textual label.  Images will be constructed 
  115.    * using the style system.
  116.    * 
  117.    * @param int             x        the x position of the interactor.
  118.    * @param int             y        the y position of the interactor.
  119.    * @param String          label    the text to draw on the button.
  120.    * @param callback_object call_obj the callback object.
  121.    */
  122.   public button(
  123.     int              x,
  124.     int              y,
  125.     String           label,
  126.     callback_object  call_obj) 
  127. {
  128.       super(x,y,null,null,call_obj);
  129.  
  130.       /* sanity check */
  131.       if (label==null) {
  132.     label="";
  133.       }
  134.       /* save the text for a second */
  135.       _text= label;
  136.       _picture=null;
  137.  
  138.       /* calculate correct initial size */
  139.       style_changed();
  140.     }
  141.  
  142.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  143.  
  144.   /** 
  145.    * Constructor based on a loaded_image and we assume you will 
  146.    * use constraints to position it. We build the button via the
  147.    * style system.
  148.    *
  149.    * @param loaded_image    img      the image to draw on the button 
  150.    * @param callback_object call_obj the callback object.
  151.    */
  152.   public button(
  153.     loaded_image img,
  154.     callback_object  call_obj) 
  155. {
  156.       super(0,0,null,null,call_obj);
  157.  
  158.       /* set the right values */
  159.       _picture=img;
  160.       _text=null;
  161.  
  162.       /* calculate correct initial size */
  163.       style_changed();
  164.     }
  165.  
  166.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  167.  
  168.   /** 
  169.    * Constructor based on a textual label and we assume you will 
  170.    * use constraints to position it. We build the button via the
  171.    * style system.
  172.    *
  173.    * @param String          label    the text to draw on the button 
  174.    * @param callback_object call_obj the callback object.
  175.    */
  176.   public button(
  177.     String           label,
  178.     callback_object  call_obj) 
  179. {
  180.       super(0,0,null,null,call_obj);
  181.  
  182.       /* save the other instance vars */
  183.       _callback_obj   = call_obj;
  184.  
  185.       /* sanity check */
  186.       if (label==null) {
  187.     label="";
  188.       }
  189.       /* save the text for a second */
  190.       _text= label;
  191.  
  192.       /* calculate correct initial size */
  193.       style_changed();
  194.     }
  195.  
  196.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  197.  
  198.   /** 
  199.    * Border around text horizontally 
  200.    */
  201.   protected int _x_border = 10;
  202.  
  203.   /**
  204.    * Retrieve the horizontal border 
  205.    * @return int the horizontal border
  206.    */
  207.   public int x_border() {
  208.     return _x_border;
  209.   }
  210.  
  211.   /**
  212.    * Set the horizontal border.
  213.    * @param int x new amount of horizontal border.
  214.    */
  215.   public void set_x_border(int x) {
  216.     _x_border=x;
  217.     style_changed();
  218.   }
  219.  
  220.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  221.  
  222.   /** Border around text vertically */
  223.   protected int _y_border = 5;
  224.  
  225.   /**
  226.    * Retrieve the vertical border 
  227.    * @return int the vertical border
  228.    */
  229.   public int y_border() {
  230.     return _y_border;
  231.   }
  232.  
  233.   /**
  234.    * Set the vertical border.
  235.    * @param int y new amount of vertical border.
  236.    */
  237.   public void set_y_border(int y) {
  238.     _y_border=y;
  239.     style_changed();
  240.   }
  241.  
  242.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  243.  
  244.   /**
  245.    * Keep a hold the font for textual gables used by this object.
  246.    */
  247.   protected Font _font=null;
  248.  
  249.   /**
  250.    * Retrieve this object's font. If you haven't specified a font,
  251.    * you get the system default font.
  252.    */
  253.   public Font font() {
  254.     if (_font==null) {
  255.       return style_manager.default_font();
  256.     }
  257.     return _font;
  258.   }
  259.  
  260.   /** 
  261.    * Set the font for this object.
  262.    * @param Font f the new font to use on this object
  263.    */
  264.   public void set_font(Font f) {
  265.     _font=f;
  266.     style_changed();
  267.   }
  268.  
  269.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  270.  
  271.   /**
  272.    * This variable holds the text we are about to render onto 
  273.    * this button. Note that this is not consulted once we 
  274.    * have rendered the image the first time.
  275.    */
  276.   protected String _text=null;
  277.  
  278.   /**
  279.    * Get the text of this button. Note: This value might be null
  280.    * if you are currently displaying an image on this button.
  281.    * If you supplied two of your own images to make this button,
  282.    * both the value of text() and the value of picture() will
  283.    * be null, since you did not use the normal style interface
  284.    * to create your buttons.
  285.    * @return String the current text string of the button (or null)
  286.    */
  287.   public String text() { return _text;}
  288.  
  289.   /**
  290.    * Set this button to display a string. 
  291.    * @param String l the new label
  292.    */
  293.   public void set_text(String l) {
  294.     /* validity check */
  295.     if (l==null) {
  296.       l="";
  297.     }
  298.     /* set the text and the picture */
  299.     _text=l;
  300.     _picture=null;
  301.     style_changed();
  302.   }
  303.  
  304.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  305.  
  306.   /**
  307.    * Store the picture (if any) we want on this button.
  308.    */
  309.   protected loaded_image _picture=null;
  310.  
  311.   /**
  312.    * Return the picture we are using for this button. This might be
  313.    * null if we are currently displaying a string. 
  314.    * @return loaded_image the image we are display on this button or null 
  315.    *                      if no image has been supplied
  316.    */
  317.   public loaded_image picture() {
  318.     return _picture;
  319.   }
  320.  
  321.   /**
  322.    * Set the current image to display on this button.  Note: that you 
  323.    * should probably be using something on a transparent background if 
  324.    * don't want this to interfere the style system.
  325.    *
  326.    * @param loaded_image p the new picture to put on this button. 
  327.    */
  328.   public void set_picture(loaded_image p) {
  329.     _picture=p;
  330.     _text=null;
  331.     style_changed();
  332.   }
  333.  
  334.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  335.  
  336.   /**
  337.    * This function gets called to generate the images for this button
  338.    * based on the current style parameters.
  339.    */
  340.   public void style_changed() {
  341.     loaded_image img[];
  342.     style cs=style_manager.current_style();
  343.     int x_off, y_off;
  344.  
  345.     /* check to see if we are autosizing or not */
  346.     if (_autosize) { 
  347.     /* we are autosizing...are we doing a string label? */
  348.       if (_text!=null) {
  349.     /* get the new size */
  350.     img=cs.button_make_images(_text,font(),_x_border,_y_border,false);
  351.       } else {
  352.     if (_picture!=null) { 
  353.       img=cs.button_make_images(_picture.width(), _picture.height(),
  354.                     _x_border, _y_border, false);
  355.  
  356.       /* figure out how much to shift the thing*/
  357.       x_off=cs.button_x_shift();
  358.       y_off=cs.button_y_shift();
  359.       /* now put the picture on them */
  360.       img[0].get_drawable().drawImage(_picture,x_off+_x_border,
  361.                       y_off+_y_border);
  362.       img[1].get_drawable().drawImage(_picture,x_off+_x_border,
  363.                       y_off+_y_border);
  364.     } else {
  365.       /* probably a programming error */
  366.       throw new sub_arctic_error("Unable to find a either a text " +
  367.                      "label or a picture to display on "+
  368.                      "this button! "); 
  369.     }
  370.       }
  371.     } else {
  372.       /* we are not autosizing, use the size of this object ... we
  373.        subtract off the beveling areas...*/
  374.       img=cs.button_make_images(w()-(2*cs.button_x_shift()), 
  375.                 h()-(2*cs.button_y_shift()),
  376.                 0,0,false);
  377.  
  378.       /* do the work of drawing the stuff */
  379.       draw_label(img);
  380.     }
  381.     set_looks(img,null);
  382.   }
  383.  
  384.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  385.    
  386.   /**
  387.    * Draw either the text or the image of the object on the button. 
  388.    * This is here primarily to allow subclass writers to put the
  389.    * label somewhere other than in the middle. This is ONLY called
  390.    * we are not in autosize mode (since it only makes sense to put
  391.    * the label in one place in autosize mode).
  392.    * 
  393.    * @param loaded_image[] img the base images to draw on
  394.    */
  395.   public void draw_label(loaded_image[] img) {
  396.     FontMetrics metrics=manager.get_metrics(font());
  397.     int sw, fh, x, y;
  398.     drawable d;
  399.  
  400.     /* is it text */
  401.     if (_text!=null) {
  402.       sw=metrics.stringWidth(text());
  403.       fh=metrics.getHeight() - metrics.getLeading();
  404.       /* x or y might be negative, but this will show the object as "in
  405.        * the middle" of the button anyway */
  406.       x=(w()-sw)/2;
  407.       y=(h()-fh)/2;
  408.       /* get the drawables and slap this stuff down */
  409.       d=img[0].get_drawable();
  410.       d.setFont(font());
  411.       d.setColor(style_manager.default_color_scheme().foreground());
  412.       d.drawString(_text,x,y+metrics.getAscent());
  413.       d=img[1].get_drawable();
  414.       d.setFont(font());
  415.       d.setColor(style_manager.default_color_scheme().foreground());
  416.       d.drawString(_text,x,y+metrics.getAscent());
  417.     } else {
  418.       /* must be a picture */
  419.       x=(w()-_picture.width())/2;
  420.       y=(h()-_picture.height())/2;
  421.       /* again, these might be negative, but centering is still what you get */
  422.       d=img[0].get_drawable();
  423.       d.drawImage(_picture,x,y);
  424.       d=img[1].get_drawable();
  425.       d.drawImage(_picture,x,y);
  426.     }
  427.   }
  428.  
  429.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  430.  
  431.   /** 
  432.    * We need to override the end behavior of the multi-button to make
  433.    * sure we always end up in the right state.
  434.    * 
  435.    * @param event   evt          the event to be dispatched.
  436.    * @param boolean ended_inside true if the drag ended inside the object.
  437.    * @param Object  user_info     the object passed to the inout_drag agent when 
  438.    *                             this object came into the focus set.
  439.    * @return boolean true if this event has been handled.
  440.    */
  441.   public boolean inout_drag_end(
  442.     event    evt, 
  443.     boolean  ended_inside, 
  444.     Object   user_info) 
  445. {
  446.     super.inout_drag_end(evt,ended_inside,user_info);
  447.     /* if we are not in state zero, we should be */
  448.     if (cur_state()!=0) {
  449.       set_cur_state(0);
  450.     } 
  451.     return true;
  452.        
  453.   }
  454.  
  455.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  456.  
  457.   /**
  458.    * This is the storage for the autosize variable.
  459.    */
  460.   protected boolean _autosize=true;
  461.  
  462.   /**
  463.    * Retrieve the current state of autosize.
  464.    * @return boolean true if the object is autosized (and thus not resizable)
  465.    */
  466.   public boolean autosize() { return _autosize;}
  467.  
  468.   /**
  469.    * Set the current state of the autosize variable. If you change the
  470.    * state from non-autosized (false) to autosized (true) the button
  471.    * will immediately autosize itself. If you change the state to
  472.    * non-autosized from autosized, no immediate redraw is requested
  473.    * and the object will continue at its current size unless that 
  474.    * is changed.
  475.    */
  476.   public void set_autosize(boolean a) {
  477.     /* no work to do */
  478.     if (a==_autosize) {
  479.       return;
  480.     }
  481.     /* save it */
  482.     _autosize=a;
  483.     /* is it currently false and now true? */
  484.     if (a==true) {
  485.       /* update the display */
  486.       style_changed();
  487.     }
  488.   }
  489.  
  490.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  491.  
  492.   /**
  493.    * We override the intrinsic constraint function because sometimes
  494.    * we have intrinsic constraints (when autosize is on) and sometimes
  495.    * we don't. 
  496.    * @return int a constant representing what (if any) our intrinsic 
  497.    *             constraints are.
  498.    */
  499.   public int intrinsic_constraints() { 
  500.     if (_autosize) {
  501.       return W|H; 
  502.     } else {
  503.       return 0;
  504.     }
  505.   }
  506.  
  507.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  508.  
  509.   /**
  510.    * This function computes the natural size of a button. This is useful
  511.    * when you want to walk down a list (or more likely, column) of buttons
  512.    * and find out which of them has the largest natural size and then
  513.    * set all of them to that size.
  514.    *
  515.    * @return Dimension the size (in pixels) of this button at its natural size
  516.    */
  517.   public Dimension natural_size() {
  518.     loaded_image img[]=null;
  519.     style cs=style_manager.current_style();
  520.  
  521.     if (_text!=null) {
  522.       /* get the new size */
  523.       img=cs.button_make_images(_text,font(),_x_border,_y_border,false);
  524.     } else {
  525.       if (_picture!=null) { 
  526.     img=cs.button_make_images(_picture.width(), _picture.height(),
  527.                   _x_border, _y_border,false);
  528.       }
  529.     }
  530.     return new Dimension(img[0].width(),img[0].height());
  531.   }
  532.  
  533.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  534.  
  535.   /**
  536.    * We have to override how set_intrinsic_size works here, because
  537.    * sometimes we have an intrinsic size and sometimes we don't.
  538.    * Multi-button (our parent) calls this code to tell the button
  539.    * that it can't be resized, but we know that it can in some 
  540.    * cases... 
  541.    * 
  542.    * @param int wv the intrinsic width value
  543.    * @param int hv the intrinsic height value
  544.    */
  545.   public void set_intrinsic_size(int wv, int hv) 
  546. {
  547.     /* we only want this if we are automatically sizing */
  548.     if (_autosize) {
  549.       super.set_intrinsic_size(wv,hv);
  550.     }
  551.   }
  552.  
  553.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  554.    
  555.   /**
  556.    * Trap calls to set_raw_w() which will change the width. If we are
  557.    * not autosizing, we want to recalculate the images. 
  558.    * @param int w the new width value
  559.    */
  560.   public void set_raw_w(int w) 
  561. {
  562.     /* we always want the parent behavior first */
  563.     super.set_raw_w(w);
  564.     if (!_autosize) {
  565.       style_changed();
  566.     }
  567.   }
  568.  
  569.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  570.    
  571.   /**
  572.    * Trap calls to set_raw_h() which will change the height. If we are
  573.    * not autosizing, we want to recalculate the images. 
  574.    * @param int h the new height value
  575.    */
  576.   public void set_raw_h(int h) 
  577. {
  578.     /* we always want the parent behavior first */
  579.     super.set_raw_h(h);
  580.     if (!_autosize) {
  581.       style_changed();
  582.     }
  583.   }
  584.  
  585.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  586. }
  587. /*=========================== COPYRIGHT NOTICE ===========================
  588.  
  589. This file is part of the subArctic user interface toolkit.
  590.  
  591. Copyright (c) 1996 Scott Hudson and Ian Smith
  592. All rights reserved.
  593.  
  594. The subArctic system is freely available for most uses under the terms
  595. and conditions described in 
  596.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  597. and appearing in full in the lib/interactor.java source file.
  598.  
  599. The current release and additional information about this software can be 
  600. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  601.  
  602. ========================================================================*/
  603.