Skip to content

Commit

Permalink
Commit for v0.4
Browse files Browse the repository at this point in the history
Major update. A list of all the changes made since the last commit are included in the comments.
  • Loading branch information
GimmickNG authored May 28, 2018
1 parent 29f1173 commit 737cce4
Show file tree
Hide file tree
Showing 36 changed files with 2,434 additions and 1,573 deletions.
1,770 changes: 730 additions & 1,040 deletions src/airdock/AIRDock.as

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/airdock/config/DockConfig.as
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package airdock.config
import airdock.interfaces.ui.IResizer;
import flash.display.DisplayObjectContainer;
import flash.display.NativeWindowInitOptions;

/**
* Base configuration class for creating a Docker instance.
* @author Gimmick
Expand Down
1 change: 1 addition & 0 deletions src/airdock/config/PanelConfig.as
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package airdock.config
private var num_height:Number;
private var b_resizable:Boolean;
private var b_dockable:Boolean;

/**
* Creates a new panel configuration instance.
* By default, panels are resizable and dockable unless explicitly set otherwise.
Expand Down
142 changes: 142 additions & 0 deletions src/airdock/delegates/ContainerDelegate.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package airdock.delegates
{
import airdock.events.PropertyChangeEvent;
import airdock.interfaces.display.IDisplayFilter;
import airdock.interfaces.docking.IContainer;
import airdock.interfaces.ui.IPanelList;
import airdock.util.PropertyChangeProxy;
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.IEventDispatcher;

/**
* ...
* @author Gimmick
*/
public class ContainerDelegate implements IEventDispatcher
{
private var cl_baseContainer:IContainer;
private var cl_changeProxy:PropertyChangeProxy;
private var cl_displayFilterDelegate:DisplayFilterDelegate;
public function ContainerDelegate(container:IContainer)
{
cl_baseContainer = container;
cl_changeProxy = new PropertyChangeProxy(container)
cl_displayFilterDelegate = new DisplayFilterDelegate(container)
}

public function dispatchChanging(property:String, oldValue:Object, newValue:Object):Boolean {
return dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGING, property, oldValue, newValue, true, true))
}

public function dispatchChanged(property:String, oldValue:Object, newValue:Object):void {
dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGED, property, oldValue, newValue, true, false))
}

public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
cl_baseContainer.addEventListener(type, listener, useCapture, priority, useWeakReference);
}

public function dispatchEvent(event:Event):Boolean {
return cl_baseContainer.dispatchEvent(event);
}

public function hasEventListener(type:String):Boolean {
return cl_baseContainer.hasEventListener(type);
}

public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
cl_baseContainer.removeEventListener(type, listener, useCapture);
}

public function willTrigger(type:String):Boolean {
return cl_baseContainer.willTrigger(type);
}

public function applyFilters(filters:Vector.<IDisplayFilter>):void {
cl_displayFilterDelegate.applyFilters(filters);
}

public function clearFilters(filters:Vector.<IDisplayFilter>):void {
cl_displayFilterDelegate.clearFilters(filters);
}

public function get displayFilters():Vector.<IDisplayFilter>
{
var filters:Vector.<IDisplayFilter> = cl_changeProxy.displayFilters as Vector.<IDisplayFilter>;
return filters && filters.concat();
}

public function set displayFilters(value:Vector.<IDisplayFilter>):void
{
cl_displayFilterDelegate.clearFilters(cl_changeProxy.displayFilters as Vector.<IDisplayFilter>)
cl_changeProxy.displayFilters = value && value.concat();
cl_displayFilterDelegate.applyFilters(value)
}

public function get sideCode():int {
return cl_changeProxy.sideCode;
}

public function set sideCode(sideCode:int):void {
cl_changeProxy.sideCode = sideCode
}

public function get sideSize():Number {
return cl_changeProxy.sideSize;
}

public function set sideSize(value:Number):void {
cl_changeProxy.sideSize = value
}

public function get containerState():Boolean {
return cl_changeProxy.containerState;
}

public function set containerState(value:Boolean):void {
cl_changeProxy.containerState = value;
}

public function get maxSideSize():Number {
return cl_changeProxy.maxSideSize;
}

public function set maxSideSize(value:Number):void {
cl_changeProxy.maxSideSize = value;
}

public function get minSideSize():Number {
return cl_changeProxy.minSideSize;
}

public function set minSideSize(value:Number):void {
cl_changeProxy.minSideSize = value;
}

public function get panelList():IPanelList {
return cl_changeProxy.panelList;
}

public function set panelList(panelList:IPanelList):void {
cl_changeProxy.panelList = panelList
}

public function get width():Number {
return cl_changeProxy.width;
}

public function set width(width:Number):void {
cl_changeProxy.width = width
}

public function get height():Number {
return cl_changeProxy.height;
}

public function set height(height:Number):void {
cl_changeProxy.height = height;
}
}

}
41 changes: 41 additions & 0 deletions src/airdock/delegates/DisplayFilterDelegate.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package airdock.delegates
{
import airdock.interfaces.display.IDisplayFilter;
import airdock.interfaces.display.IFilterable;
import airdock.util.PropertyChangeProxy;
import flash.display.DisplayObject;
/**
* ...
* @author Gimmick
*/
public class DisplayFilterDelegate
{
private var cl_target:IFilterable
public function DisplayFilterDelegate(target:IFilterable) {
cl_target = target
}

/**
* Applies the given filters to the target.
* @param filters A Vector of IDisplayFilters which are to be applied to the target.
*/
public function applyFilters(filters:Vector.<IDisplayFilter>):void
{
for (var i:int = int(filters && filters.length) - 1; i >= 0; --i) {
filters[i].apply(cl_target);
}
}

/**
* Removes the given filters from the target.
* @param filters A Vector of IDisplayFilters which are to be removed from the target.
*/
public function clearFilters(filters:Vector.<IDisplayFilter>):void
{
for (var k:int = int(filters && filters.length) - 1; k >= 0; --k) {
filters[k].remove(cl_target);
}
}
}

}
67 changes: 17 additions & 50 deletions src/airdock/delegates/DockHelperDelegate.as
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package airdock.delegates
{
import airdock.enums.PanelContainerSide;
import airdock.events.DockEvent;
import airdock.interfaces.ui.IDockHelper;
import airdock.util.IPair;
import flash.desktop.NativeDragManager;
import flash.display.DisplayObject;
import flash.display.InteractiveObject;
Expand All @@ -26,53 +24,32 @@ package airdock.delegates
{
cl_dockHelper = dockHelper;
dct_dockTargets = new Dictionary(true)
dockHelper.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, acceptDragDrop, false, 0, true)
dockHelper.addEventListener(NativeDragEvent.NATIVE_DRAG_OVER, displayTargetsOnDrag, false, 0, true)
}

public function addTarget(target:DisplayObject, side:int):void {
dct_dockTargets[target] = side;
dockHelper.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, displayTargetsOnDrag, false, 0, true)
}

/**
* Adds the targets specified to the list of all dock helper candidates/targets.
* Each target is a key-value pair with the key as the target displayObject and the value as the side it represents.
* In other words, the value is the side that a container or panel will be attached to when dropped on that target.
* @param targets A Vector of key-value pairs with the key as the target displayObject and the value as the side which it represents.
* @see airdock.util.IPair
* Adds the target specified to the list of all dock helper candidates/targets.
* Each target is the target DisplayObject associated with the side it represents.
* The side is the side that a container or panel will be attached to when dropped on the target.
* @param target The target DisplayObject instance.
* @param side The side(s) which the target is associated with as a String.
* Multiple sides can be added as a string sequence of sides.
*/
public function addTargets(targets:Vector.<IPair>):void
{
for (var i:uint = 0; i < targets.length; ++i)
{
var target:IPair = targets[i];
if (target && target.key is DisplayObject && target.value !== null) {
addTarget(target.key as DisplayObject, int(target.value));
}
}
public function addTarget(target:DisplayObject, side:String):void {
dct_dockTargets[target] = side;
}

public function removeTarget(target:DisplayObject):void {
delete dct_dockTargets[target];
}

public function removeTargets(targets:Vector.<DisplayObject>):void
{
for (var i:uint = 0; i < targets.length; ++i)
{
var target:DisplayObject = targets[i] as DisplayObject
if(target) {
removeTarget(target)
}
}
}

public function getSideFrom(dropTarget:DisplayObject):int
public function getSideFrom(dropTarget:DisplayObject):String
{
if(dropTarget in dct_dockTargets) {
return int(dct_dockTargets[dropTarget])
return String(dct_dockTargets[dropTarget])
}
return PanelContainerSide.FILL
return PanelContainerSide.STRING_FILL
}

public function get targets():Vector.<DisplayObject>
Expand All @@ -84,25 +61,15 @@ package airdock.delegates
return targets;
}

/**
* Dispatches a DockEvent when the user has dropped the panel or container on any of the sprites of this object, prior to the end of the drag-dock action.
*/
private function acceptDragDrop(evt:NativeDragEvent):void
{
if (evt.clipboard.hasFormat(str_panelFormat) || evt.clipboard.hasFormat(str_containerFormat)) {
dispatchEvent(new DockEvent(DockEvent.DRAG_COMPLETING, evt.clipboard, evt.target as DisplayObject, true, true))
}
}

private function displayTargetsOnDrag(evt:NativeDragEvent):void
{
var currentTarget:InteractiveObject = evt.target as InteractiveObject
if (!(currentTarget in dct_dockTargets && (evt.clipboard.hasFormat(str_panelFormat) || evt.clipboard.hasFormat(str_containerFormat)))) {
return;
if ((currentTarget in dct_dockTargets && (evt.clipboard.hasFormat(str_panelFormat) || evt.clipboard.hasFormat(str_containerFormat))))
{
cl_dockHelper.hide() //show only the current target
cl_dockHelper.show(new <DisplayObject>[currentTarget])
NativeDragManager.acceptDragDrop(currentTarget)
}
cl_dockHelper.hide(); //hides all the targets
cl_dockHelper.show(new <DisplayObject>[currentTarget]) //except the current one
NativeDragManager.acceptDragDrop(currentTarget)
}

public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
Expand Down
Loading

4 comments on commit 737cce4

@GimmickNG
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking Changes:

The main breaking changes are listed below. Again, most of these involve changes to interfaces or events; if you are not using them, you will most likely not be affected (unless you make use of movePanelToContainer, which is the only miscellaneous breaking change listed). However, if you implement any custom class(es) which make use of these interfaces, then they will have to be updated.

Changes:

  • Changed the ITreeResolver interface to accept a Vector.<DisplayObject> instead of just 2 for the findCommonParent() method
  • Changed the IDockTarget interface to return a side (string) sequence for the getSideFrom() method instead of a single (integer) side code.
  • Changed the getPanelContainers() method in the IBasicDocker interface to getPanelContainer() - now returns a single IPanel's parked IContainer, not a list of key-value IPanel-IContainer values.
  • Resizing is now done through a ratio, not a coordinate value
  • Renamed the PanelPropertyChangeEvent class to PropertyChangeEvent since it was being used by non-panel classes as well, to report property changes; see also the PropertyChangeProxy class.
  • PanelContainerEvent and its subclass events (PanelContainerStateEvent) now accept a Vector.<IPanel> instance instead of a single IPanel. In effect, multiple IPanel instances can take part in a drag-dock operation.
  • Used string versions of PanelContainerSide in place of integer versions wherever possible. Note that the integer representation of PanelContainerSIde is deprecated and will be removed in a future release.

Removals:

  • Removed the DockEvent class and its corresponding events due to needless redundancy
  • Removed the deprecated movePanelToContainer method from the IBasicDocker interface
  • Removed the implementations of the IPair interface (StaticPair, DynamicPair, etc.) because none of them were visible in public-facing code; instead replaced with a stronger typed PanelSideSequence internal class where use of a panel-container key-value pair was required.

@GimmickNG
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other Changes & Additions

Other changes and additions, some minor and others semi-major, are listed in further comments.

@GimmickNG
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additions:

  • ContainerDelegate - basic delegation class for the IContainer interface, currently used by the DefaultContainer class.
  • PropertyChangeProxy - a delegate Proxy which dispatches PropertyChangeEvent.PROPERTY_CHANGING and PropertyChangeEvent.PROPERTY_CHANGED events before and after a change occurs, used primarily in delegation classes (PanelDelegate, ContainerDelegate, etc.)
  • IDisposable interface - The interface indicating which classes have a dispose() method which needs to be called prior to removal (i.e. simple garbage collection does not suffice for removal of an IDisposable implementer)
  • IStrategy and IDockerStrategy interfaces - Interfaces for docking strategy; used by Dockers to carry out drag-dock operations
  • Added destinationFormat in the IDockFormat interface
  • Added resizeHelper and dockHelper (get, set) to the ICustomizableDocker interface
  • Added integratePanel to the IBasicDocker interface - this interface method moves a panel to the last non-parked root IContainer it occupied
  • Added treeResolver and dockFormat to the IBasicDocker interface
  • DefaultResizer now collapses containers on double-click
  • Select multiple panels' tabs in DefaultPanelList by holding down the Ctrl or Command key when clicking on panel tabs
  • 3 dots are shown in corner of DefaultPanelList when extra panel tabs are hidden from view (e.g. if its width is too small to display all tabs)
  • Added the ResizerStrategy class - the Docker offloads the display and resizing of containers to this class.
  • Added the DockHelperStrategy class - the Docker offloads the display and selection of containers (by the user) during a drag-dock operation to this class.
  • Added the ResizerEvent class - event class which is used by ResizerStrategy and ResizerDelegate to handle resize operations (not to be confused with the PanelContainerEvent.RESIZE event)
  • Added the DisplayFilterDelegate class - handles the applying and clearing of display filters to and from a given target

Changes:

  • More focus on functional-style programming instead of normal for-loops (using forEach, filter, map, etc. where possible)
  • ResizerDelegate's getDragBounds() now returns a rectangle clipped to the actual width and height reported by the container, not that of getBounds() (since getBounds() reports incorrect sizes when the default width and height properties are overridden in a DisplayObject)
  • Refactored the AIRDock class to remove unnecessary and redundant dock operations.
  • The AIRDock class now uses the PropertyChangeProxy for storing data instead of storing it directly.
  • Changed how a drag-docking operation is carried out.

@GimmickNG
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed how a drag-docking operation is carried out.

To elaborate:

The old method

Previously, a drag-docking operation required the use of the Clipboard property of the NativeDragEvent, and 2 docking formats within. They were used to store 2 things:

  • A panel which was taking part in a drag-dock operation
    • This was usually set to a single panel, and only if the initiating IPanelList instance of the IContainer had set it that way - whenever a panel tab in the list was dragged, for example.
  • A container which was taking part in a drag-dock operation
    • Unlike the panel, the container was always set, and usually by the related IContainer - it intercepted the PanelContainerEvent.DRAG_REQUESTED (and other) events and redispatched them, attaching itself as the related IContainer.

This led to a series of if (panel) { ... } else if (container) { ... } chains throughout the code, and was not really too maintainable. Also, an IDockHelper instance would accept the NativeDragEvent (via NativeDragManager.acceptDragDrop() method) and would dispatch a DockEvent.DRAG_COMPLETING event in its listener.

The new way™

In the new system, however, there are 3 items in the drag-dock clipboard:

  • A Vector.<IPanel>, performing the same function as the panel, previously; however, multiple panels are included - not just one. If the entire container contents are to be dragged, this parameter is not set to null (unlike before); instead, all the panels in the container are passed as a parameter.
  • A container - no change here
  • An IDragDockFormat instance - this is just a normal Object used to store data about the destination IContainer and the side it is to be attached to.

Now in a drag-dock operation, when the IDockHelper instance accepts the drag, then instead of dispatching a separate DockEvent.DRAG_COMPLETING event, it instead changes the contents of the clipboard - that is, it modifies the IDragDockFormat's properties (since writing to the clipboard is not allowed, but modifying an existing object's properties are) to include information about the destination IContainer instance and the side sequence it is to be attached to.

The host (originating/initiating) Docker instance, at the end of the native drag (i.e. NativeDragEvent.NATIVE_DRAG_COMPLETE) then inspects the IDragDockFormat properties to decide where to dock the panels.

This change was done to better facilitate cross-docking - now, the host Docker can easily check for crossDockingPolicy violations, and is less roundabout.

Please sign in to comment.