1  /*
     2   Copyright aswing.org, see the LICENCE.txt.
     3  */
     4   
     5  import org.aswing.*;
     6  import org.aswing.plaf.*;
     7   
     8  /**
     9   *
    10   * @author iiley
    11   */
    12  class org.aswing.AbstractButton extends Component{
    13  	
    14  	public static var ON_SET_FOCUS:String = "onSetFocus";
    15   	public static var ON_KILL_FOCUS:String = "onKillFocus";
    16   	
    17  			
    18  	/**
    19  	 * When the button's state changed.
    20  	 *<br>
    21  	 * onStateChanged Event{source:AbstractButton}
    22  	 */	
    23  	public static var ON_STATE_CHANGED:String = "onStateChanged";//Component.ON_STATE_CHANGED; 	
    24   	
    25  	/**
    26  	 * When the button's selection changed. fired when diselected or selected.
    27  	 *<br>
    28  	 * onSelectionChanged Event{source:AbstractButton}
    29  	 */	
    30  	public static var ON_SELECTION_CHANGED:String = "onSelectionChanged";  	
    31   	
    32  	/**
    33  	 * A fast access to ASWingConstants Constant
    34  	 * @see org.aswing.ASWingConstants
    35  	 */
    36  	public static var CENTER:Number  = ASWingConstants.CENTER;
    37  	/**
    38  	 * A fast access to ASWingConstants Constant
    39  	 * @see org.aswing.ASWingConstants
    40  	 */
    41  	public static var TOP:Number     = ASWingConstants.TOP;
    42  	/**
    43  	 * A fast access to ASWingConstants Constant
    44  	 * @see org.aswing.ASWingConstants
    45  	 */
    46      public static var LEFT:Number    = ASWingConstants.LEFT;
    47  	/**
    48  	 * A fast access to ASWingConstants Constant
    49  	 * @see org.aswing.ASWingConstants
    50  	 */
    51      public static var BOTTOM:Number  = ASWingConstants.BOTTOM;
    52   	/**
    53  	 * A fast access to ASWingConstants Constant
    54  	 * @see org.aswing.ASWingConstants
    55  	 */
    56      public static var RIGHT:Number   = ASWingConstants.RIGHT;
    57  	/**
    58  	 * A fast access to ASWingConstants Constant
    59  	 * @see org.aswing.ASWingConstants
    60  	 */        
    61  	public static var HORIZONTAL:Number = ASWingConstants.HORIZONTAL;
    62  	/**
    63  	 * A fast access to ASWingConstants Constant
    64  	 * @see org.aswing.ASWingConstants
    65  	 */
    66  	public static var VERTICAL:Number   = ASWingConstants.VERTICAL;
    67          
    68      /** The data model that determines the button's state. */
    69      private var model:ButtonModel;
    70      private var modelStateListener:Object;
    71      private var modelSelectionListener:Object;
    72  
    73      private var text:String; // for BeanBox
    74      private var margin:Insets;
    75      private var defaultMargin:Insets;
    76  
    77      // Button icons
    78      private var       defaultIcon:Icon;
    79      private var       pressedIcon:Icon;
    80      private var       disabledIcon:Icon;
    81  
    82      private var       selectedIcon:Icon;
    83      private var       disabledSelectedIcon:Icon;
    84  
    85      private var       rolloverIcon:Icon;
    86      private var       rolloverSelectedIcon:Icon;
    87      
    88      // Display properties
    89      private var    paintBorder:Boolean;
    90      private var    rolloverEnabled:Boolean;
    91  
    92      // Icon/Label Alignment
    93      private var        verticalAlignment:Number;
    94      private var        horizontalAlignment:Number;
    95      
    96      private var        verticalTextPosition:Number;
    97      private var        horizontalTextPosition:Number;
    98  
    99      private var        iconTextGap:Number;
   100      
   101      /**
   102       * AbstractButton(text:String, icon:Icon)<br>
   103       * AbstractButton(text:String)<br>
   104       * AbstractButton(icon:Icon)
   105       * <p>
   106       * AbstractButton is abstract, can't be constructed.
   107       */
   108      private function AbstractButton(text, icon:Icon){
   109      	super();
   110      	if(text instanceof Icon){
   111      		icon = Icon(text);
   112      		text = null;
   113      	}
   114  		setName("AbstractButton");
   115      	paintBorder = true;
   116      	rolloverEnabled = false;
   117      	
   118      	verticalAlignment = CENTER;
   119      	horizontalAlignment = CENTER;
   120      	verticalTextPosition = CENTER;
   121      	horizontalTextPosition = RIGHT;
   122      	
   123      	iconTextGap = 2;
   124      	
   125      	setText(text);
   126      	setIcon(icon);
   127      }
   128  
   129      /**
   130       * Returns the model that this button represents.
   131       * @return the <code>model</code> property
   132       * @see #setModel()
   133       */
   134      public function getModel():ButtonModel{
   135          return model;
   136      }
   137      
   138      /**
   139       * Sets the model that this button represents.
   140       * @param m the new <code>ButtonModel</code>
   141       * @see #getModel()
   142       */
   143      public function setModel(newModel:ButtonModel):Void {
   144          
   145          var oldModel:ButtonModel = getModel();
   146          
   147          if (oldModel != null) {
   148              oldModel.removeEventListener(modelStateListener);
   149              oldModel.removeEventListener(modelSelectionListener);
   150              modelStateListener = null;
   151              modelSelectionListener = null;
   152          }
   153          
   154          model = newModel;
   155          
   156          if (newModel != null) {
   157              modelStateListener = newModel.addChangeListener(__onModelStateChanged, this);
   158              modelSelectionListener = newModel.addSelectionListener(__onModelSelectionChanged, this);
   159          }
   160  
   161          if (newModel != oldModel) {
   162              revalidate();
   163              repaint();
   164          }
   165      }
   166  	
   167  	private function __onModelStateChanged(event:Event):Void{
   168  		fireStateChanged();
   169  	}
   170  	
   171  	private function __onModelSelectionChanged(event:Event):Void{
   172  		dispatchEvent(ON_SELECTION_CHANGED, createEventObj(ON_SELECTION_CHANGED));
   173  	}
   174      
   175      /**
   176       * Returns the L&F object that renders this component.
   177       * @return the ButtonUI object
   178       * @see #setUI()
   179       */
   180      public function getUI():ButtonUI {
   181          return ButtonUI(ui);
   182      }
   183  
   184      
   185      /**
   186       * Sets the L&F object that renders this component.
   187       * @param ui the <code>ButtonUI</code> L&F object
   188       * @see #getUI()
   189       */
   190      public function setUI(ui:ButtonUI):Void {
   191          super.setUI(ui);
   192      }
   193  
   194      
   195      /**
   196       * Resets the UI property to a value from the current look
   197       * and feel.  Subtypes of <code>AbstractButton</code>
   198       * should override this to update the UI. For
   199       * example, <code>JButton</code> might do the following:
   200       * <pre>
   201       *      setUI(ButtonUI(UIManager.getUI(this)));
   202       * </pre>
   203       */
   204      public function updateUI():Void{
   205      }
   206      
   207      /**
   208       * addActionListener(fuc:Function, obj:Object)<br>
   209       * addActionListener(fuc:Function)
   210       * <p>
   211       * Adds a action listener to this button. Buttons fire a action event when 
   212       * user released on it.
   213       * @param fuc the listener function.
   214       * @param Context in which to run the function of param func.
   215       * @return the listener just added.
   216       * @see EventDispatcher#ON_ACT
   217       * @see Component#ON_RELEASE
   218       */
   219      public function addActionListener(fuc:Function, obj:Object):Object{
   220      	return addEventListener(ON_ACT, fuc, obj);
   221      }
   222      
   223      /**
   224       * addSelectionListener(fuc:Function, obj:Object)<br>
   225       * addSelectionListener(fuc:Function)
   226       * <p>
   227       * Adds a action listener to this button's selection change event. 
   228       * @param fuc the listener function.
   229       * @param Context in which to run the function of param func.
   230       * @return the listener just added.
   231       * @see #ON_SELECTION_CHANGED
   232       * @see ButtonModel#addSelectionListener()
   233       */    
   234      public function addSelectionListener(func:Function, obj:Object):Object{
   235  		return addEventListener(ON_SELECTION_CHANGED, func, obj);
   236  	}
   237      
   238      /**
   239       * Enabled (or disabled) the button.
   240       * @param b  true to enable the button, otherwise false
   241       */
   242     public function setEnabled(b:Boolean):Void{
   243  		if (!b && model.isRollOver()) {
   244  	    	model.setRollOver(false);
   245  		}
   246          super.setEnabled(b);
   247          model.setEnabled(b);
   248      }    
   249  
   250      /**
   251       * Returns the state of the button. True if the
   252       * toggle button is selected, false if it's not.
   253       * @return true if the toggle button is selected, otherwise false
   254       */
   255      public function isSelected():Boolean{
   256          return model.isSelected();
   257      }
   258      
   259      /**
   260       * Sets the state of the button. Note that this method does not
   261       * trigger an Event for users.
   262       * Call <code>doClick</code> to perform a programatic action change.
   263       *
   264       * @param b  true if the button is selected, otherwise false
   265       */
   266      public function setSelected(b:Boolean):Void{
   267          model.setSelected(b);
   268      }
   269      
   270      /**
   271       * Sets the <code>rolloverEnabled</code> property, which
   272       * must be <code>true</code> for rollover effects to occur.
   273       * The default value for the <code>rolloverEnabled</code>
   274       * property is <code>false</code>.
   275       * Some look and feels might not implement rollover effects;
   276       * they will ignore this property.
   277       * 
   278       * @param b if <code>true</code>, rollover effects should be painted
   279       * @see #isRollOverEnabled()
   280       */
   281      public function setRollOverEnabled(b:Boolean):Void{
   282      	if(rolloverEnabled != b){
   283      		rolloverEnabled = b;
   284      		repaint();
   285      	}
   286      }
   287      
   288      /**
   289       * Gets the <code>rolloverEnabled</code> property.
   290       *
   291       * @return the value of the <code>rolloverEnabled</code> property
   292       * @see #setRollOverEnabled()
   293       */    
   294      public function isRollOverEnabled():Boolean{
   295      	return rolloverEnabled;
   296      }
   297  
   298  	/**
   299  	 * Sets space for margin between the button's border and
   300       * the label. Setting to <code>null</code> will cause the button to
   301       * use the default margin.  The button's default <code>Border</code>
   302       * object will use this value to create the proper margin.
   303       * However, if a non-default border is set on the button, 
   304       * it is that <code>Border</code> object's responsibility to create the
   305       * appropriate margin space (else this property will
   306       * effectively be ignored).
   307       *
   308       * @param m the space between the border and the label
   309  	 */
   310  	public function setMargin(m:Insets):Void{
   311          // Cache the old margin if it comes from the UI
   312          if(m instanceof UIResource) {
   313              defaultMargin = m;
   314          }
   315          
   316          // If the client passes in a null insets, restore the margin
   317          // from the UI if possible
   318          if(m == null && defaultMargin != null) {
   319              m = defaultMargin;
   320          }
   321  
   322          var old:Insets = margin;
   323          margin = m;
   324          if (old == null || !m.equals(old)) {
   325              revalidate();
   326              //repaint();
   327          }
   328  	}
   329  	
   330  	public function getMargin():Insets{
   331  		if(margin == null){
   332  			 return defaultMargin;
   333  		}else{
   334  			return (new Insets()).addInsets(margin);
   335  		}
   336  	}
   337  	
   338  	/**
   339  	 * Sets text and icon at one method here.
   340  	 * @param text the text for the button
   341  	 * @param icon the default icon for the button
   342  	 * @see #setText()
   343  	 * @see #setIcon()
   344  	 */
   345  	public function setContent(text:String, icon:Icon):Void{
   346  		if(this.text != text){
   347  			this.text = text;
   348  		}
   349  		if(this.defaultIcon != icon){
   350  			uninstallIconWhenNextPaint(this.defaultIcon);
   351  			this.defaultIcon = icon;
   352  		}
   353  		repaint();
   354  		invalidate();
   355  	}
   356  	
   357  	public function setText(text:String):Void{
   358  		if(this.text != text){
   359  			this.text = text;
   360  			repaint();
   361  			invalidate();
   362  		}
   363  	}
   364  	
   365  	public function getText():String{
   366  		return text;
   367  	}
   368  	
   369  	public function setIcon(defaultIcon:Icon):Void{
   370  		if(this.defaultIcon != defaultIcon){
   371  			uninstallIconWhenNextPaint(this.defaultIcon);
   372  			this.defaultIcon = defaultIcon;
   373  			repaint();
   374  			invalidate();
   375  		}
   376  	}
   377  
   378  	public function getIcon():Icon{
   379  		return defaultIcon;
   380  	}
   381      
   382      /**
   383       * Returns the pressed icon for the button.
   384       * @return the <code>pressedIcon</code> property
   385       * @see #setPressedIcon()
   386       */
   387      public function getPressedIcon():Icon {
   388          return pressedIcon;
   389      }
   390      
   391      /**
   392       * Sets the pressed icon for the button.
   393       * @param pressedIcon the icon used as the "pressed" image
   394       * @see #getPressedIcon()
   395       */
   396      public function setPressedIcon(pressedIcon:Icon):Void {
   397          var oldValue:Icon = this.pressedIcon;
   398          this.pressedIcon = pressedIcon;
   399          if (pressedIcon != oldValue) {
   400          	uninstallIconWhenNextPaint(oldValue);
   401              if (getModel().isPressed()) {
   402                  repaint();
   403              }
   404          }
   405      }
   406  
   407      /**
   408       * Returns the selected icon for the button.
   409       * @return the <code>selectedIcon</code> property
   410       * @see #setSelectedIcon()
   411       */
   412      public function getSelectedIcon():Icon {
   413          return selectedIcon;
   414      }
   415      
   416      /**
   417       * Sets the selected icon for the button.
   418       * @param selectedIcon the icon used as the "selected" image
   419       * @see #getSelectedIcon()
   420       */
   421      public function setSelectedIcon(selectedIcon:Icon):Void {
   422          var oldValue:Icon = this.selectedIcon;
   423          this.selectedIcon = selectedIcon;
   424          if (selectedIcon != oldValue) {
   425          	uninstallIconWhenNextPaint(oldValue);
   426              if (isSelected()) {
   427                  repaint();
   428              }
   429          }
   430      }
   431  
   432      /**
   433       * Returns the rollover icon for the button.
   434       * @return the <code>rolloverIcon</code> property
   435       * @see #setRollOverIcon()
   436       */
   437      public function getRollOverIcon():Icon {
   438          return rolloverIcon;
   439      }
   440      
   441      /**
   442       * Sets the rollover icon for the button.
   443       * @param rolloverIcon the icon used as the "rollover" image
   444       * @see #getRollOverIcon()
   445       */
   446      public function setRollOverIcon(rolloverIcon:Icon):Void {
   447          var oldValue:Icon = this.rolloverIcon;
   448          this.rolloverIcon = rolloverIcon;
   449          setRollOverEnabled(true);
   450          if (rolloverIcon != oldValue) {
   451          	uninstallIconWhenNextPaint(oldValue);
   452              if(getModel().isRollOver()){
   453              	repaint();
   454              }
   455          }
   456        
   457      }
   458      
   459      /**
   460       * Returns the rollover selection icon for the button.
   461       * @return the <code>rolloverSelectedIcon</code> property
   462       * @see #setRollOverSelectedIcon()
   463       */
   464      public function getRollOverSelectedIcon():Icon {
   465          return rolloverSelectedIcon;
   466      }
   467      
   468      /**
   469       * Sets the rollover selected icon for the button.
   470       * @param rolloverSelectedIcon the icon used as the
   471       *		"selected rollover" image
   472       * @see #getRollOverSelectedIcon()
   473       */
   474      public function setRollOverSelectedIcon(rolloverSelectedIcon:Icon):Void {
   475          var oldValue:Icon = this.rolloverSelectedIcon;
   476          this.rolloverSelectedIcon = rolloverSelectedIcon;
   477          setRollOverEnabled(true);
   478          if (rolloverSelectedIcon != oldValue) {
   479          	uninstallIconWhenNextPaint(oldValue);
   480              if (isSelected()) {
   481                  repaint();
   482              }
   483          }
   484      }
   485      
   486      /**
   487       * Returns the icon used by the button when it's disabled.
   488       * If no disabled icon has been set, the button constructs
   489       * one from the default icon. 
   490       * <p>
   491       * The disabled icon really should be created 
   492       * (if necessary) by the L&F.-->
   493       *
   494       * @return the <code>disabledIcon</code> property
   495       * @see #getPressedIcon()
   496       * @see #setDisabledIcon()
   497       */
   498      public function getDisabledIcon():Icon {
   499          if(disabledIcon == null) {
   500              if(defaultIcon != null) {
   501                  disabledIcon = new GrayFilteredIcon(defaultIcon);
   502              }
   503          }
   504          return disabledIcon;
   505      }
   506      
   507      /**
   508       * Sets the disabled icon for the button.
   509       * @param disabledIcon the icon used as the disabled image
   510       * @see #getDisabledIcon()
   511       */
   512      public function setDisabledIcon(disabledIcon:Icon):Void {
   513          var oldValue:Icon = this.disabledIcon;
   514          this.disabledIcon = disabledIcon;
   515          if (disabledIcon != oldValue) {
   516          	uninstallIconWhenNextPaint(oldValue);
   517              if (!isEnabled()) {
   518                  repaint();
   519              }
   520          }
   521      }
   522      
   523      /**
   524       * Returns the icon used by the button when it's disabled and selected.
   525       * If not no disabled selection icon has been set, the button constructs
   526       * one from the selection icon. 
   527       * <p>
   528       * The disabled selection icon really should be 
   529       * created (if necessary) by the L&F. -->
   530       *
   531       * @return the <code>disabledSelectedIcon</code> property
   532       * @see #getPressedIcon()
   533       * @see #setDisabledIcon()
   534       */
   535      public function getDisabledSelectedIcon():Icon {
   536          if(disabledSelectedIcon == null) {
   537              if(selectedIcon != null) {
   538                  disabledSelectedIcon = new GrayFilteredIcon(selectedIcon);
   539              } else {
   540                  return getDisabledIcon();
   541              }
   542          }
   543          return disabledSelectedIcon;
   544      }
   545  
   546      /**
   547       * Sets the disabled selection icon for the button.
   548       * @param disabledSelectedIcon the icon used as the disabled
   549       * 		selection image
   550       * @see #getDisabledSelectedIcon()
   551       */
   552      public function setDisabledSelectedIcon(disabledSelectedIcon:Icon):Void {
   553          var oldValue:Icon = this.disabledSelectedIcon;
   554          this.disabledSelectedIcon = disabledSelectedIcon;
   555          if (disabledSelectedIcon != oldValue) {
   556          	uninstallIconWhenNextPaint(oldValue);
   557              if (!isEnabled() && isSelected()) {
   558                  repaint();
   559                  revalidate();
   560              }
   561          }
   562      }
   563  
   564      /**
   565       * Returns the vertical alignment of the text and icon.
   566       *
   567       * @return the <code>verticalAlignment</code> property, one of the
   568       *		following values: 
   569       * <ul>
   570       * <li>ASWingConstants.CENTER (the default)
   571       * <li>ASWingConstants.TOP
   572       * <li>ASWingConstants.BOTTOM
   573       * </ul>
   574       */
   575      public function getVerticalAlignment():Number {
   576          return verticalAlignment;
   577      }
   578      
   579      /**
   580       * Sets the vertical alignment of the icon and text.
   581       * @param alignment  one of the following values:
   582       * <ul>
   583       * <li>ASWingConstants.CENTER (the default)
   584       * <li>ASWingConstants.TOP
   585       * <li>ASWingConstants.BOTTOM
   586       * </ul>
   587       */
   588      public function setVerticalAlignment(alignment:Number):Void {
   589          if (alignment == verticalAlignment){
   590          	return;
   591          }else{
   592          	verticalAlignment = alignment;
   593          	repaint();
   594          }
   595      }
   596      
   597      /**
   598       * Returns the horizontal alignment of the icon and text.
   599       * @return the <code>horizontalAlignment</code> property,
   600       *		one of the following values:
   601       * <ul>
   602       * <li>ASWingConstants.RIGHT (the default)
   603       * <li>ASWingConstants.LEFT
   604       * <li>ASWingConstants.CENTER
   605       * </ul>
   606       */
   607      public function getHorizontalAlignment():Number{
   608          return horizontalAlignment;
   609      }
   610      
   611      /**
   612       * Sets the horizontal alignment of the icon and text.
   613       * @param alignment  one of the following values:
   614       * <ul>
   615       * <li>ASWingConstants.RIGHT (the default)
   616       * <li>ASWingConstants.LEFT
   617       * <li>ASWingConstants.CENTER
   618       * </ul>
   619       */
   620      public function setHorizontalAlignment(alignment:Number):Void {
   621          if (alignment == horizontalAlignment){
   622          	return;
   623          }else{
   624          	horizontalAlignment = alignment;     
   625          	repaint();
   626          }
   627      }
   628  
   629      
   630      /**
   631       * Returns the vertical position of the text relative to the icon.
   632       * @return the <code>verticalTextPosition</code> property, 
   633       *		one of the following values:
   634       * <ul>
   635       * <li>ASWingConstants.CENTER  (the default)
   636       * <li>ASWingConstants.TOP
   637       * <li>ASWingConstants.BOTTOM
   638       * </ul>
   639       */
   640      public function getVerticalTextPosition():Number{
   641          return verticalTextPosition;
   642      }
   643      
   644      /**
   645       * Sets the vertical position of the text relative to the icon.
   646       * @param alignment  one of the following values:
   647       * <ul>
   648       * <li>ASWingConstants.CENTER (the default)
   649       * <li>ASWingConstants.TOP
   650       * <li>ASWingConstants.BOTTOM
   651       * </ul>
   652       */
   653      public function setVerticalTextPosition(textPosition:Number):Void {
   654          if (textPosition == verticalTextPosition){
   655  	        return;
   656          }else{
   657          	verticalTextPosition = textPosition;
   658          	repaint();
   659          }
   660      }
   661      
   662      /**
   663       * Returns the horizontal position of the text relative to the icon.
   664       * @return the <code>horizontalTextPosition</code> property, 
   665       * 		one of the following values:
   666       * <ul>
   667       * <li>ASWingConstants.RIGHT (the default)
   668       * <li>ASWingConstants.LEFT
   669       * <li>ASWingConstants.CENTER
   670       * </ul>
   671       */
   672      public function getHorizontalTextPosition():Number {
   673          return horizontalTextPosition;
   674      }
   675      
   676      /**
   677       * Sets the horizontal position of the text relative to the icon.
   678       * @param textPosition one of the following values:
   679       * <ul>
   680       * <li>ASWingConstants.RIGHT (the default)
   681       * <li>ASWingConstants.LEFT
   682       * <li>ASWingConstants.CENTER
   683       * </ul>
   684       */
   685      public function setHorizontalTextPosition(textPosition:Number):Void {
   686          if (textPosition == horizontalTextPosition){
   687          	return;
   688          }else{
   689          	horizontalTextPosition = textPosition;
   690          	repaint();
   691          }
   692      }
   693      
   694      /**
   695       * Returns the amount of space between the text and the icon
   696       * displayed in this button.
   697       *
   698       * @return an int equal to the number of pixels between the text
   699       *         and the icon.
   700       * @see #setIconTextGap()
   701       */
   702      public function getIconTextGap():Number {
   703          return iconTextGap;
   704      }
   705  
   706      /**
   707       * If both the icon and text properties are set, this property
   708       * defines the space between them.  
   709       * <p>
   710       * The default value of this property is 4 pixels.
   711       * 
   712       * @see #getIconTextGap()
   713       */
   714      public function setIconTextGap(iconTextGap:Number):Void {
   715          var oldValue:Number = this.iconTextGap;
   716          this.iconTextGap = iconTextGap;
   717          if (iconTextGap != oldValue) {
   718              revalidate();
   719              repaint();
   720          }
   721      }
   722      
   723  
   724  	//-----------------------button's event method to change state-------------
   725  	private function __onPress():Void{
   726  		getModel().setPressed(true);
   727  		super.__onPress();
   728  	}
   729  	
   730  	private function __onRelease():Void{
   731  		getModel().setReleased(true);
   732  		super.__onRelease();
   733  		dispatchEvent(ON_ACT, createEventObj(ON_ACT));
   734  	}
   735  	
   736  	private function __onReleaseOutside():Void{
   737  		getModel().setRollOver(false);
   738  		getModel().setReleased(true);
   739  		super.__onReleaseOutside();
   740  	}
   741  	
   742  	private function __onRollOver():Void{
   743  		getModel().setRollOver(true);
   744  		super.__onRollOver();
   745  	}
   746  	
   747  	private function __onRollOut():Void{
   748  		getModel().setRollOver(false);
   749  		super.__onRollOut();
   750  	}    
   751  }
   752