1  /*
     2   Copyright aswing.org, see the LICENCE.txt.
     3  */
     4   
     5  import org.aswing.ASColor;
     6  import org.aswing.ASWingConstants;
     7  import org.aswing.ASWingUtils;
     8  import org.aswing.Component;
     9  import org.aswing.geom.Dimension;
    10  import org.aswing.geom.Rectangle;
    11  import org.aswing.graphices.Graphics;
    12  import org.aswing.Icon;
    13  import org.aswing.JButton;
    14  import org.aswing.JFrame;
    15  import org.aswing.plaf.basic.frame.FrameTitleBar;
    16  import org.aswing.plaf.basic.frame.TitleBarLayout;
    17  import org.aswing.plaf.ComponentUI;
    18  import org.aswing.UIManager;
    19  import org.aswing.utils.Delegate;
    20  
    21  /**
    22   * @author iiley
    23   */
    24  class org.aswing.plaf.basic.frame.TitleBarUI extends ComponentUI {
    25  	
    26  	private static var ICON_TEXT_GAP:Number = 2;
    27  	
    28  	private var titleTextField:TextField;
    29  	private var titleBar:FrameTitleBar;
    30  	private var frame:JFrame;
    31  	private var defaultIcon:Icon;
    32  	
    33  	private var iconifiedButton:JButton;
    34  	private var resizeButton:JButton;
    35  	private var closeButton:JButton;
    36  	
    37  	private var iconifiedIcon:Icon;
    38  	private var normalIcon:Icon;
    39  	private var maximizeIcon:Icon;
    40  	private var closeIcon:Icon;
    41  	
    42  	private var activeColor:ASColor;
    43  	private var activeTextColor:ASColor;
    44  	private var inactiveColor:ASColor;
    45  	private var inactiveTextColor:ASColor;
    46  	private var activeBorderColor:ASColor;
    47  	private var inactiveBorderColor:ASColor;
    48  	
    49  	
    50  	
    51  	private var stateChangedListener:Object;
    52  	private var sizeChangedListener:Object;
    53  	private var locationChangedListener:Object;
    54  	private var stageChangedListener:Object;
    55  	private var activeListener:Object;
    56  	private var unactiveListener:Object;
    57  	private var stateChangeSize:Boolean;
    58  	private var stateChangeLocation:Boolean;
    59  	private var lastNormalStateBounds:Rectangle;
    60  	
    61  	public function TitleBarUI() {
    62  		super();
    63  		stateChangeSize = false;
    64  		stateChangeLocation = false;
    65  		lastNormalStateBounds = new Rectangle();
    66  		checkRectsForCountLayout();
    67  	}
    68  	
    69  	public function installUI(c:Component):Void{
    70      	titleBar = FrameTitleBar(c);
    71      	frame = titleBar.getFrame();
    72  		
    73  		installDefaults();
    74  		installComponents();
    75  		installListeners();
    76      }
    77      private function installDefaults():Void{
    78      	
    79  		titleBar.setLayout(TitleBarLayout.createInstance());
    80  		
    81      	defaultIcon = UIManager.getIcon("Frame.icon");
    82      	
    83  		activeColor         = UIManager.getColor("Frame.activeCaption");
    84  		activeTextColor     = UIManager.getColor("Frame.activeCaptionText");
    85  		inactiveColor       = UIManager.getColor("Frame.inactiveCaption");
    86  		inactiveTextColor   = UIManager.getColor("Frame.inactiveCaptionText"); 	
    87  		activeBorderColor   = UIManager.getColor("Frame.activeCaptionBorder");
    88  		inactiveBorderColor = UIManager.getColor("Frame.inactiveCaptionBorder"); 	
    89  		
    90  		iconifiedIcon = UIManager.getIcon("Frame.iconifiedIcon");
    91  	 	normalIcon    = UIManager.getIcon("Frame.normalIcon");
    92  		maximizeIcon  = UIManager.getIcon("Frame.maximizeIcon");
    93  		closeIcon     = UIManager.getIcon("Frame.closeIcon");
    94  		
    95  		
    96          titleBar.setBackground(activeColor);
    97          titleBar.setForeground(activeTextColor);
    98          titleBar.setOpaque(true);
    99      }
   100  	private function installComponents() : Void {
   101  		iconifiedButton = new JButton(null, iconifiedIcon);
   102  		resizeButton    = new JButton(null, maximizeIcon);
   103  		closeButton     = new JButton(null, closeIcon);
   104  		titleBar.append(iconifiedButton);
   105  		titleBar.append(resizeButton);
   106  		titleBar.append(closeButton);
   107  		
   108  		iconifiedButton.addActionListener(__iconifiedPressed, this);
   109  		resizeButton.addActionListener(__resizePressed, this);
   110  		closeButton.addActionListener(__closePressed, this);
   111  	}
   112  	private function installListeners():Void{
   113  		stateChangedListener = frame.addEventListener(JFrame.ON_STATE_CHANGED, __stateChanged, this);
   114  		sizeChangedListener = frame.addEventListener(JFrame.ON_RESIZED, __sizeChanged, this);
   115  		locationChangedListener = frame.addEventListener(Component.ON_MOVED, __frameMoved, this);
   116  		stageChangedListener = new Object();
   117  		stageChangedListener.onResize = Delegate.create(this, __stageChanged);
   118  		Stage.addListener(stageChangedListener);
   119  		activeListener = frame.addEventListener(JFrame.ON_WINDOW_ACTIVATED, __frameActived, this);
   120  		unactiveListener = frame.addEventListener(JFrame.ON_WINDOW_DEACTIVATED, __frameUnactived, this);
   121  	}
   122  	
   123      public function uninstallUI(c:Component):Void{
   124  		uninstallDefaults();
   125  		uninstallComponents();
   126  		uninstallListeners();
   127      	titleTextField.removeTextField();
   128      }
   129  	private function uninstallDefaults():Void{
   130  	}
   131  	private function uninstallComponents():Void{
   132  		titleBar.remove(iconifiedButton);
   133  		titleBar.remove(resizeButton);
   134  		titleBar.remove(closeButton);
   135  	}
   136  	private function uninstallListeners():Void{
   137  		frame.removeEventListener(stateChangedListener);
   138  		frame.removeEventListener(sizeChangedListener);
   139  		frame.removeEventListener(locationChangedListener);
   140  		Stage.removeListener(stageChangedListener);
   141  		frame.removeEventListener(activeListener);
   142  		frame.removeEventListener(unactiveListener);
   143  	}
   144  
   145  	public function create(c:Component):Void{
   146  		titleTextField = c.createTextField("titleText");
   147  		
   148  		adjustButtons();
   149  		adjustResizerEnable();
   150  		
   151  		if(frame.getState() == JFrame.NORMAL){
   152  			lastNormalStateBounds.setRect(frame.getBounds());
   153  		}
   154  	}
   155  	
   156  	//------------------------------------------
   157  	private function __frameActived():Void{
   158  		titleBar.repaint();
   159  	}
   160  	private function __frameUnactived():Void{
   161  		titleBar.repaint();
   162  	}	
   163  	private function __stageChanged():Void{
   164  		if(Stage.scaleMode != "noScale"){
   165  			return;
   166  		}
   167  		if(isMaximized()){
   168  			setSizeToFixMaxmimized();
   169  			frame.revalidateIfNecessary();
   170  		}
   171  	}
   172  	private function __iconifiedPressed():Void{
   173  		frame.setState(JFrame.ICONIFIED);
   174  	}
   175  	private function __resizePressed():Void{
   176  		if(isNormalIcon()){
   177  			frame.setState(JFrame.NORMAL);
   178  		}else{
   179  			frame.setState(JFrame.MAXIMIZED);
   180  		}
   181  	}
   182  	private function __closePressed():Void{
   183  		frame.closeReleased();
   184  	}
   185  	
   186  	private function __frameMoved():Void{
   187  		if(stateChangeLocation){
   188  			stateChangeLocation = false;
   189  		}else{
   190  			lastNormalStateBounds.setLocation(frame.getLocation());
   191  		}
   192  	}
   193  	
   194  	private function __sizeChanged():Void{
   195  		if(stateChangeSize){
   196  			stateChangeSize = false;
   197  		}else{
   198  			lastNormalStateBounds.setSize(frame.getSize());
   199  		}
   200  	}
   201  	
   202  	private function __stateChanged():Void{
   203  		var state:Number = frame.getState();
   204  		if(state != JFrame.ICONIFIED 
   205  			&& state != JFrame.NORMAL
   206  			&& state != JFrame.MAXIMIZED_HORIZ
   207  			&& state != JFrame.MAXIMIZED_VERT
   208  			&& state != JFrame.MAXIMIZED){
   209  			state = JFrame.NORMAL;
   210  		}
   211  		if(state == JFrame.ICONIFIED){
   212  			iconifiedButton.setVisible(false);
   213  			switchResizeIcon();
   214  			var iconifiedSize:Dimension = titleBar.getMinimumSize();
   215  			stateChangeSize = true;
   216  			frame.setSize(frame.getInsets().roundsSize(iconifiedSize));
   217  		}else if(state == JFrame.NORMAL){
   218  			stateChangeSize = true;
   219  			frame.setBounds(lastNormalStateBounds);
   220  			if(isNeedToViewIconifiedButton())
   221  				iconifiedButton.setVisible(true);
   222  			switchToMaximizButton();
   223  		}else{
   224  			setSizeToFixMaxmimized();
   225  		}
   226  		frame.revalidateIfNecessary();
   227  	}
   228  	
   229  	private function setSizeToFixMaxmimized():Void{
   230  		var state:Number = frame.getState();
   231  		var maxBounds:Rectangle = frame.getMaximizedBounds();
   232  		var b:Rectangle = frame.getBounds();
   233  		if((state & JFrame.MAXIMIZED_HORIZ) == JFrame.MAXIMIZED_HORIZ){
   234  			b.x = maxBounds.x;
   235  			b.width = maxBounds.width;
   236  		}
   237  		if((state & JFrame.MAXIMIZED_VERT) == JFrame.MAXIMIZED_VERT){
   238  			b.y = maxBounds.y;
   239  			b.height = maxBounds.height;
   240  		}
   241  		stateChangeSize = true;
   242  		stateChangeLocation = true;
   243  		frame.setBounds(b);
   244  		if(isNeedToViewIconifiedButton())
   245  			iconifiedButton.setVisible(true);
   246  		switchToNormalButton();
   247  	}
   248  	
   249  	public function isNormalIcon():Boolean{
   250  		return resizeButton.getIcon() == normalIcon;
   251  	}
   252  		
   253  	public function switchResizeIcon():Void{
   254  		if(isNormalIcon()){
   255  			switchToMaximizButton();
   256  		}else{
   257  			switchToNormalButton();
   258  		}
   259  	}
   260  	
   261  	public function switchToMaximizButton():Void{
   262  		resizeButton.setIcon(maximizeIcon);
   263  	}
   264  	
   265  	public function switchToNormalButton():Void{
   266  		resizeButton.setIcon(normalIcon);
   267  	}
   268  	
   269  	private static var viewRect:Rectangle;
   270      private static var textRect:Rectangle;
   271      private static var iconRect:Rectangle;
   272         
   273      private static function checkRectsForCountLayout():Void{
   274      	if(viewRect == null){
   275  			viewRect = new Rectangle();
   276      		textRect = new Rectangle();
   277      		iconRect = new Rectangle();
   278      	}
   279      }
   280      	
   281  	public function paint(c:Component, g:Graphics, r:Rectangle):Void{
   282  		super.paint(c, g, r);
   283  		
   284  		var icon:Icon = frame.getIcon();
   285  		
   286  		if(icon == null){
   287  			icon = defaultIcon;
   288  		}
   289  		
   290  		icon.uninstallIcon(c);
   291  		
   292      	viewRect.setRect(r);
   293      	var tlayout:TitleBarLayout = TitleBarLayout(titleBar.getLayout());
   294      	var buttonsWidth:Number = 0;
   295      	var buttonCount:Number = 0;
   296      	if(iconifiedButton.isVisible()){
   297      		buttonCount ++;
   298      		buttonsWidth += iconifiedButton.getWidth();
   299      	} 
   300      	if(resizeButton.isVisible()){
   301      		buttonCount ++;
   302      		buttonsWidth += resizeButton.getWidth();
   303      	} 
   304      	if(closeButton.isVisible()){
   305      		buttonCount ++;
   306      		buttonsWidth += closeButton.getWidth();
   307      	} 
   308      	viewRect.width -= buttonsWidth + Math.max(0, buttonCount-1)*tlayout.getHorizontalGap();
   309      		
   310      	textRect.x = textRect.y = textRect.width = textRect.height = 0;
   311          iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
   312  
   313          // layout the text and icon
   314          var text:String = ASWingUtils.layoutCompoundLabel(
   315              c.getFont(), frame.getTitle(), icon, 
   316              ASWingConstants.CENTER, ASWingConstants.LEFT,
   317              ASWingConstants.CENTER, ASWingConstants.RIGHT,
   318              viewRect, iconRect, textRect, 
   319  	    	frame.getTitle() == null ? 0 : ICON_TEXT_GAP);
   320  	   	
   321      	if(icon != null){
   322      		icon.paintIcon(c, g, iconRect.x, iconRect.y);
   323      	}
   324      	
   325          if (text != null && text != ""){
   326  			titleTextField.text = text;
   327  	    	ASWingUtils.applyTextFontAndColor(titleTextField, frame.getFont(), frame.getForeground());
   328  			titleTextField._x = textRect.x;
   329  			titleTextField._y = textRect.y;
   330          }
   331  		
   332  		adjustButtons();
   333  		adjustResizerEnable();
   334  	}
   335  	
   336  	private function isMaximized():Boolean{
   337  		var state:Number = frame.getState();
   338  		return ((state & JFrame.MAXIMIZED_HORIZ) == JFrame.MAXIMIZED_HORIZ)
   339  			|| ((state & JFrame.MAXIMIZED_VERT) == JFrame.MAXIMIZED_VERT);
   340  	}
   341  	
   342  	private function isNeedToViewIconifiedButton():Boolean{
   343  		return frame.isResizable() && frame.getState() != JFrame.ICONIFIED;
   344  	}
   345  	
   346  	private function isNeedToViewResizeButton():Boolean{
   347  		return frame.isResizable();
   348  	}
   349  	
   350  	private function isNeedToViewCloseButton():Boolean{
   351  		return frame.isClosable();
   352  	}
   353  
   354  	private function adjustButtons() : Void {
   355  		iconifiedButton.setVisible(isNeedToViewIconifiedButton());
   356  		resizeButton.setVisible(isNeedToViewResizeButton());
   357  		closeButton.setVisible(isNeedToViewCloseButton());
   358  	}
   359  
   360  	private function adjustResizerEnable() : Void {
   361  		frame.getResizer().setEnabled(frame.isResizable() && frame.getState() == JFrame.NORMAL);
   362  	}
   363  
   364  }
   365