Я пытаюсь создать систему приложений на основе окон (если хотите, мини-GUI) в среде Adobe Air (Flex 4). При реализации перетаскивания окон я учитываю z-порядок, обновляя глубину теперь активированного окна из глобальной функции, которая обновляет скрытую переменную каждый раз, когда к ней обращаются (гарантируя, что выбранное окно всегда находится сверху). (Примечание: я выбрал глобальные функции вместо набора событий, потому что целью этого действия является немедленное получение возвращаемого значения, а не указание какой-либо другой части системы что-либо делать, поэтому я считаю, что это допустимое исключение из обычное предложение «использовать события для связи между объектами».) Я столкнулся с десятками возможных решений для создания и вызова этой глобальной функции, но единственное, что до сих пор работало, это:
event.target.parentApplication.obtainNewHigherDepth()
Как видите, на самом деле это не глобальный вызов функции, а вызов родительского элемента верхнего уровня (или более верхнего уровня), который содержит необходимую функцию. В моих тестовых случаях это работает просто отлично, даже когда я добавляю компоненты внутреннего содержимого в окна. Однако при добавлении карты Google в качестве содержимого окна нажатие на кнопки типа карты приводит к ошибке:
ReferenceError: Error #1069: Property parentApplication not found on com.google.maps.wrappers.
WrappableSprite and there is no default value.
at Window/selectWindow()[C:\Users\d04000196\Desktop\Projects\UI Concepting\ErrorExample\src\Window.mxml:18]
Похоже, что API Google Map пытается вызвать мой код в неверном контексте. Будучи новичком во Flex / Air, я не знаю, как связать соответствующий контекст, как это можно сделать с Javascript. Но это не должно быть необходимым.
Если есть лучший способ создать и вызвать действительно глобальную функцию (и использовать соответствующую глобальную переменную), эта проблема не выровненных контекстов не будет иметь значения. Или, если есть известное решение для этой конкретной проблемы с API Карт Google, это также могло бы работать как решение (но не как будущее).
Указанные ниже файлы представляют собой минимальный код, необходимый для иллюстрации проблемы.
Для настройки
- Загрузите указанные ниже файлы в стандартный пакет нового проекта Adobe Air через Flash Builder.
- Загрузите API Карт Google и добавьте библиотеку в проект .
Для иллюстрации ошибки
- Запустить приложение
- Нажмите кнопку «Открыть карту»
- Нажмите любую из кнопок типа карты в правом верхнем углу области карты
ExampleError.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="800" height="600"
frameRate="60"
applicationComplete="init()">
<fx:Script>
<![CDATA[
// ********************
// THE PART IN QUESTION
// ********************
private var maxDepth:Number = 0;
public function obtainNewHigherDepth():Number {
return (maxDepth++);
}
private function openAMap(event:MouseEvent):void {
var window:Window = new Window();
var map:CustomMap = new CustomMap();
window.x = 160;
window.titleBarText.text = "Map"
window.content.addElement(map);
this.addElement(window);
}
private function init():void {
openMapButton.addEventListener(MouseEvent.CLICK, openAMap);
statusBar.visible = false;
}
]]>
</fx:Script>
<s:VGroup x="10" y="10" width="135" height="580">
<s:Button label="Open a Map" id="openMapButton" />
</s:VGroup>
</s:WindowedApplication>
Window.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:visuals="com.lsus.udop.visuals.*"
width="400" height="400" depth="1"
initialize="init()">
<fx:Script>
<![CDATA[
import flash.events.MouseEvent;
private var moving:Boolean = false;
private var relativeX:Number;
private var relativeY:Number;
private function selectWindow(event:MouseEvent):void {
// ********************
// THE PART IN QUESTION
// ********************
this.depth = event.target.parentApplication.obtainNewHigherDepth();
}
private function windowDragMouseDown(event:MouseEvent):void {
relativeX = event.stageX - this.x;
relativeY = event.stageY - this.y;
moving = true;
this.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, windowDragMouseMove, true);
this.systemManager.addEventListener(MouseEvent.MOUSE_UP, windowDragMouseUp, true);
}
private function windowDragMouseMove(event:MouseEvent):void {
event.stopImmediatePropagation();
this.x = event.stageX - relativeX;
this.y = event.stageY - relativeY;
}
private function windowDragMouseUp(event:MouseEvent):void {
event.stopImmediatePropagation();
moving = false;
this.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, windowDragMouseMove, true);
this.systemManager.removeEventListener(MouseEvent.MOUSE_UP, windowDragMouseUp , true);
}
private function init():void {
this.addEventListener(MouseEvent.MOUSE_DOWN, selectWindow);
titleBar.addEventListener(MouseEvent.MOUSE_DOWN, windowDragMouseDown);
this.depth = this.parentApplication.obtainNewHigherDepth();
}
]]>
</fx:Script>
<s:Rect width="100%" height="100%">
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<s:Group id="titleBar" top="0" left="0" right="0" height="20">
<s:Label text="Title Bar Text" id="titleBarText" top="5" bottom="0" left="5" color="0xffffff" />
</s:Group>
<s:Group id="content" top="21" left="1" right="1" bottom="1" />
</s:Group>
CustomMap.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%"
initialize="init()">
<fx:Script>
<![CDATA[
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapType;
import com.google.maps.controls.MapTypeControl;
private function onMapReady(event:MapEvent):void {
map.enableScrollWheelZoom();
map.addControl(new MapTypeControl());
}
private function init():void {
map.addEventListener(MapEvent.MAP_READY, onMapReady);
}
]]>
</fx:Script>
<maps:Map xmlns:maps="com.google.maps.*"
url="http://code.google.com/apis/maps/"
key="ABQIAAAAiVMBdjzjhpqA-qSxuuT0cRT2yXp_ZAY8_ufC3CFXhHIE1NvwkxQ4igt7gOyr4x11lp3ETKR2fOH5Hw"
sensor="false"
width="100%" height="100%" id="map" />
</s:Group>
Обновление
Обнаружил другой вопрос только сейчас (никогда не выходит из строя, не так ли?), Это:
FlexGlobals.topLevelApplication
, кажется, дает мне то, что я ищу. Недостатком является отсутствие безопасности, если мой оконный компонент когда-либо используется за пределами этого конкретного приложения, но поскольку это не планируется, этого должно быть достаточно. Тем не менее, если есть лучшее решение, я бы хотел услышать его.