blob: 36abbe7568a94077e904888032bb569c4a838175 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package spark.components.windowClasses
{
import flash.display.DisplayObject;
import flash.display.NativeWindowDisplayState;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.NativeWindowDisplayStateEvent;
import flash.system.Capabilities;
import mx.core.IWindow;
import mx.core.mx_internal;
import spark.components.Button;
import spark.components.supportClasses.SkinnableComponent;
import spark.components.supportClasses.TextBase;
import spark.events.SkinPartEvent;
import spark.primitives.BitmapImage;
import spark.skins.*;
import spark.skins.spark.windowChrome.MacTitleBarSkin;
import spark.skins.spark.windowChrome.TitleBarSkin;
use namespace mx_internal;
//--------------------------------------
// SkinStates
//--------------------------------------
/**
* The title bar is enabled and the application is maximized.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinState("normalAndMaximized")]
/**
* The title bar is disabled and the application is maximized.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinState("disabledAndMaximized")]
//--------------------------------------
// Excluded APIs
//--------------------------------------
[Exclude(name="focusBlendMode", kind="style")]
[Exclude(name="focusThickness", kind="style")]
/**
* The TitleBar class defines the default title bar for a
* WindowedApplication or a Window container.
*
* @see mx.core.Window
* @see mx.core.WindowedApplication
*
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public class TitleBar extends SkinnableComponent
{
include "../../core/Version.as";
//--------------------------------------------------------------------------
//
// Class methods
//
//--------------------------------------------------------------------------
/**
* @private
*/
private static function isMac():Boolean
{
return Capabilities.os.substring(0, 3) == "Mac";
}
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function TitleBar():void
{
super();
doubleClickEnabled = true;
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
addEventListener(MouseEvent.DOUBLE_CLICK, doubleClickHandler);
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
* This is the actual object created from the _titleIcon class
*/
mx_internal var titleIconObject:Object;
//--------------------------------------------------------------------------
//
// Skin Parts
//
//--------------------------------------------------------------------------
//----------------------------------
// closeButton
//----------------------------------
/**
* The skin part that defines the Button control that corresponds to the close button.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinPart (required="true")]
public var closeButton:Button;
//----------------------------------
// maximizeButton
//----------------------------------
/**
* The skin part that defines the Button control that corresponds to the maximize button.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinPart (required="false")]
public var maximizeButton:Button;
//----------------------------------
// minimizeButton
//----------------------------------
/**
* The skin part that defines the Button control that corresponds to the minimize button.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinPart (required="false")]
public var minimizeButton:Button;
//----------------------------------
// titleIconImage
//----------------------------------
/**
* The title icon in the TitleBar.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinPart (required="false")]
public var titleIconImage:BitmapImage;
//----------------------------------
// titleTextField
//----------------------------------
/**
* The skin part that defines the UITextField control that displays the application title text.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
[SkinPart (required="false")]
public var titleText:TextBase;
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// title
//----------------------------------
/**
* Storage for the title property.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
private var _title:String = "";
/**
* @private
*/
private var titleChanged:Boolean = false;
/**
* The title that appears in the window title bar and
* the dock or taskbar.
*
* @default ""
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get title():String
{
return _title;
}
/**
* @private
*/
public function set title(value:String):void
{
_title = value;
titleChanged = true;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
//----------------------------------
// titleIcon
//----------------------------------
/**
* @private
* Storage for the titleIcon property.
*/
private var _titleIcon:Class;
/**
* @private
*/
private var titleIconChanged:Boolean = false;
/**
* The icon displayed in the title bar.
*
* @default null
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
public function get titleIcon():Class
{
return _titleIcon;
}
/**
* @private
*/
public function set titleIcon(value:Class):void
{
_titleIcon = value;
titleIconChanged = true;
invalidateProperties();
invalidateSize();
}
//----------------------------------
// window
//----------------------------------
/**
* The IWindow that owns this TitleBar.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
private function get window():IWindow
{
var p:DisplayObject = parent;
while (p && !(p is IWindow))
p = p.parent;
return IWindow(p);
}
//--------------------------------------------------------------------------
//
// Overridden methods: SkinnableComponent
//
//--------------------------------------------------------------------------
/**
* @private
*
* When we are running on the mac, switch to the mac skin and continue the load.
*
*/
override protected function attachSkin():void
{
if (isMac() && getStyle("skinClass") == TitleBarSkin)
{
setStyle("skinClass", MacTitleBarSkin);
}
super.attachSkin();
}
//--------------------------------------------------------------------------
//
// Overridden methods: SkinnableContainer
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == titleText)
{
titleText.text = title;
}
else if (instance == closeButton)
{
closeButton.focusEnabled = false;
closeButton.addEventListener(MouseEvent.MOUSE_DOWN, button_mouseDownHandler);
closeButton.addEventListener(MouseEvent.CLICK, closeButton_clickHandler);
}
else if (instance == minimizeButton)
{
minimizeButton.focusEnabled = false;
minimizeButton.enabled = window.minimizable;
minimizeButton.addEventListener(MouseEvent.MOUSE_DOWN,
button_mouseDownHandler);
minimizeButton.addEventListener(MouseEvent.CLICK,
minimizeButton_clickHandler);
}
else if (instance == maximizeButton)
{
maximizeButton.focusEnabled = false;
maximizeButton.enabled = window.maximizable;
maximizeButton.addEventListener(MouseEvent.MOUSE_DOWN,
button_mouseDownHandler);
maximizeButton.addEventListener(MouseEvent.CLICK,
maximizeButton_clickHandler);
var targetWindow:DisplayObject = DisplayObject(window);
targetWindow.addEventListener(
NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE,
window_displayStateChangeHandler, false, 0, true);
// Add this listener so we can remove the display state change handler
// if our window is reskinned. This fixes an RTE when the titleBar
// display state handler ran without a window after being reskinned.
targetWindow.addEventListener(SkinPartEvent.PART_REMOVED, partRemovedHandler,
false, 0, true);
}
}
/**
* @private
*/
override protected function partRemoved(partName:String, instance:Object):void
{
super.partRemoved(partName, instance);
if (instance == closeButton)
{
closeButton.removeEventListener(MouseEvent.CLICK, closeButton_clickHandler);
}
else if (instance == minimizeButton)
{
minimizeButton.removeEventListener(MouseEvent.MOUSE_DOWN,
button_mouseDownHandler);
minimizeButton.removeEventListener(MouseEvent.CLICK,
minimizeButton_clickHandler);
}
else if (instance == maximizeButton)
{
maximizeButton.removeEventListener(MouseEvent.MOUSE_DOWN,
button_mouseDownHandler);
maximizeButton.removeEventListener(MouseEvent.CLICK,
maximizeButton_clickHandler);
var targetWindow:DisplayObject = DisplayObject(window);
targetWindow.removeEventListener(
NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE,
window_displayStateChangeHandler);
targetWindow.removeEventListener(SkinPartEvent.PART_REMOVED, partRemovedHandler);
}
}
/**
* @private
*/
override protected function commitProperties():void
{
super.commitProperties();
if (titleChanged)
{
titleText.text = _title;
titleChanged = false;
}
if (titleIconChanged)
{
if (titleIconObject)
{
titleIconImage.source = null;
titleIconObject = null;
}
if (_titleIcon && titleIconImage)
{
titleIconObject = new _titleIcon();
titleIconImage.source = titleIconObject;
}
titleIconChanged = false;
}
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Skin states support
//
//--------------------------------------------------------------------------
/**
* Returns the name of the state to be applied to the skin. For example, a
* Button component could return the String "up", "down", "over", or "disabled"
* to specify the state.
*
* <p>A subclass of SkinnableComponent must override this method to return a value.</p>
*
* @return A string specifying the name of the state to apply to the skin.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
override protected function getCurrentSkinState():String
{
if (!window.nativeWindow.closed &&
window.nativeWindow.displayState == NativeWindowDisplayState.MAXIMIZED)
{
return enabled ? "normalAndMaximized" : "disabledAndMaximized";
}
return enabled ? "normal" : "disabled";
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* @private
*/
private function mouseDownHandler(event:MouseEvent):void
{
window.nativeWindow.startMove();
event.stopPropagation();
}
/**
* The method that handles a <code>doubleClick</code> event in a platform-appropriate manner.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion AIR 1.5
* @productversion Flex 4
*/
protected function doubleClickHandler(event:MouseEvent):void
{
if (isMac())
{
window.minimize();
}
else
{
if (window.nativeWindow.displayState ==
NativeWindowDisplayState.MAXIMIZED)
{
window.restore();
}
else
{
window.maximize();
}
}
}
/**
* @private
* Used to swallow mousedown so bar is not draggable from buttons
*/
private function button_mouseDownHandler(event:MouseEvent):void
{
event.stopPropagation();
}
/**
* @private
*/
private function minimizeButton_clickHandler(event:Event):void
{
window.minimize();
}
/**
* @private
*/
private function maximizeButton_clickHandler(event:Event):void
{
if (window.nativeWindow.displayState ==
NativeWindowDisplayState.MAXIMIZED)
{
window.restore();
}
else
{
window.maximize();
}
// work around for bugs SDK-9547 & SDK-21190
maximizeButton.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
}
/**
* @private
*/
private function closeButton_clickHandler(event:Event):void
{
window.close();
}
/**
* @private
*/
private function window_displayStateChangeHandler(
event:NativeWindowDisplayStateEvent):void
{
// If we have been minimized or maximized then invalidate our skin state
// so the maximize and restore buttons will be updated.
if (event.afterDisplayState == NativeWindowDisplayState.MAXIMIZED ||
event.afterDisplayState == NativeWindowDisplayState.NORMAL)
{
invalidateSkinState();
}
}
/**
* @private
*/
private function partRemovedHandler(event:SkinPartEvent):void
{
if (event.instance == this)
{
var targetWindow:DisplayObject = DisplayObject(window);
targetWindow.removeEventListener(
NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE,
window_displayStateChangeHandler);
targetWindow.removeEventListener(SkinPartEvent.PART_REMOVED, partRemovedHandler);
}
}
}
}