1  /*
     2   Copyright aswing.org, see the LICENCE.txt.
     3  */
     4   
     5  import org.aswing.*;
     6  import org.aswing.geom.*;
     7  import org.aswing.plaf.*;
     8  import org.aswing.plaf.basic.*;
     9  import org.aswing.graphices.*;
    10   
    11  /**
    12   * Basic RadioButton implementation.
    13   * To implement a Diff RadioButton UI, generally you should:
    14   * <ul>
    15   * 	<li>extends your ToggleButtonUI to inherite diff features of buttons.
    16   * 	<li>implement a diff Icon for it, and put it into UI defaults with "RadioButton.icon" as key.
    17   * 	<li>initialize differnt UI defaults for buttons in your LAF class, for example: Button.border, 
    18   * 	Button.font, ToggleButton.backgound XXXButton.foreground...
    19   * </ul>
    20   * @author iiley
    21   */
    22  class org.aswing.plaf.basic.BasicRadioButtonUI extends BasicToggleButtonUI{
    23  		
    24      // Shared UI object
    25      private static var radioButtonUI:BasicRadioButtonUI;
    26      
    27      private var defaultIcon:Icon;
    28      private var defaults_radiobutton_initialized:Boolean;
    29      private static var propertyPrefix:String = "RadioButton" + ".";
    30  
    31      // ********************************
    32      //          Create PLAF
    33      // ********************************
    34      public static function createInstance(c:Component):ComponentUI {
    35      	if(radioButtonUI == null){
    36      		radioButtonUI = new BasicRadioButtonUI();
    37      	}
    38          return radioButtonUI;
    39      }
    40  
    41      private function getPropertyPrefix():String {
    42          return propertyPrefix;
    43      }
    44      
    45      public function BasicRadioButtonUI() {
    46      	super();
    47      	defaults_radiobutton_initialized = false;
    48      	checkRectsForCountLayout();
    49      }
    50      
    51      // ********************************
    52      //        Install PLAF 
    53      // ********************************
    54      private function installDefaults(b:AbstractButton):Void{
    55          super.installDefaults(b);
    56          if(!defaults_radiobutton_initialized) {
    57              defaultIcon = UIManager.getIcon(getPropertyPrefix() + "icon");
    58              defaults_initialized = true;
    59          }
    60          LookAndFeel.installBasicProperties(b, getPropertyPrefix());
    61      }
    62  
    63      // ********************************
    64      //        Uninstall PLAF 
    65      // ********************************
    66      private function uninstallDefaults(b:AbstractButton):Void{
    67          super.uninstallDefaults(b);
    68          defaults_radiobutton_initialized = false;
    69      }
    70  
    71      public function getDefaultIcon():Icon {
    72          return defaultIcon;
    73      }    
    74      
    75      /* These rectangles/insets are allocated once for all 
    76       * ButtonUI.paint() calls.  Re-using rectangles rather than 
    77       * allocating them in each paint call substantially reduced the time
    78       * it took paint to run.  Obviously, this method can't be re-entered.
    79       */
    80  	private static var viewRect:Rectangle;
    81      private static var textRect:Rectangle;
    82      private static var iconRect:Rectangle;
    83         
    84      private static function checkRectsForCountLayout():Void{
    85      	if(viewRect == null){
    86  			viewRect = new Rectangle();
    87      		textRect = new Rectangle();
    88      		iconRect = new Rectangle();
    89      	}
    90      }
    91      
    92      public function paint(c:Component, g:Graphics, r:Rectangle):Void{
    93      	var b:AbstractButton = AbstractButton(c);
    94      	var model:ButtonModel = b.getModel();
    95      	paintBackGround(b, g, r);
    96      	
    97      	var insets:Insets = b.getMargin();
    98      	if(insets != null){
    99      		r = insets.getInsideBounds(r);
   100      	}
   101      	viewRect.setRect(r);
   102      	
   103      	textRect.x = textRect.y = textRect.width = textRect.height = 0;
   104          iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
   105  
   106  		var altIcon:Icon = b.getIcon();
   107  
   108          // layout the text and icon
   109          var text:String = ASWingUtils.layoutCompoundLabel(
   110              c.getFont(), b.getText(), altIcon != null ? altIcon : getDefaultIcon(), 
   111              b.getVerticalAlignment(), b.getHorizontalAlignment(),
   112              b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
   113              viewRect, iconRect, textRect, 
   114  	    	b.getText() == null ? 0 : b.getIconTextGap());
   115  		// Paint the radio button
   116  		if (altIcon != null) {
   117  			if (!model.isEnabled()) {
   118  				if (model.isSelected()) {
   119  					altIcon = b.getDisabledSelectedIcon();
   120  				} else {
   121  					altIcon = b.getDisabledIcon();
   122  				}
   123  			} else if (model.isPressed()) {
   124  				altIcon = b.getPressedIcon();
   125  				if (altIcon == null) {
   126  					// Use selected icon
   127  					altIcon = b.getSelectedIcon();
   128  				}
   129  			} else if (model.isSelected()) {
   130  				if (b.isRollOverEnabled() && model.isRollOver()) {
   131  					altIcon = b.getRollOverSelectedIcon();
   132  					if (altIcon == null) {
   133  						altIcon = b.getSelectedIcon();
   134  					}
   135  				} else {
   136  					altIcon = b.getSelectedIcon();
   137  				}
   138  			} else if (b.isRollOverEnabled() && model.isRollOver()) {
   139  				altIcon = b.getRollOverIcon();
   140  			}
   141  
   142  			if (altIcon == null) {
   143  				altIcon = b.getIcon();
   144  			}
   145  		} else {
   146  			altIcon = getDefaultIcon();
   147  		}
   148  		unistallLastPaintIcon(b, altIcon);
   149  		altIcon.paintIcon(b, g, iconRect.x, iconRect.y);
   150      	setJustPaintedIcon(b, altIcon);
   151  	    
   152  	    //paint text
   153          if (text != null && text != ""){
   154  			paintText(b, textRect, text);
   155          }else{
   156          	getTopTextField(b).text = "";
   157          	getBottomTextField(b).text = "";
   158          }
   159      }
   160      
   161      //just fill rect with background color
   162      private function paintBackGround(c:Component, g:Graphics, b:Rectangle):Void{
   163      	if(c.isOpaque()){
   164      		fillRectBackGround(c, g, b);
   165      	}
   166      }
   167      
   168      public function getPreferredSize(c:Component):Dimension{
   169      	var b:AbstractButton = AbstractButton(c);
   170      	var icon:Icon = b.getIcon();
   171      	if(icon == null) icon = getDefaultIcon();
   172      	var text:String = b.getText();
   173      	return getButtonPreferredSize(b, icon, text);
   174      }
   175  
   176      public function getMinimumSize(c:Component):Dimension{
   177      	var b:AbstractButton = AbstractButton(c);
   178      	var icon:Icon = b.getIcon();
   179      	if(icon == null) icon = getDefaultIcon();
   180      	var text:String = b.getText();
   181      	return getButtonMinimumSize(b, icon, text);
   182      }    
   183  }
   184