Enabling Drag and Drop Functionality
Introduction
You can add functionality to your components. Drag and drop is a user action that involves dragging components or objects using a pointing device and dropping
them over other objects on the frame, which results in some action. For example, a
text entry that contains the name of a SAS table could be dragged onto a data table and then dropped to display the contents of the SAS table in the data table. Drag
and drop also works between objects on different frames.
Components that can be dragged are called drag sites, and components that can receive
a dropped are called drop sites. When an object is dropped, data is passed to the and an action occurs. The action is determined by:
-
the form in which the data is passed, called the
-
the of
The data representation is the form of data that a is capable of transferring and a drop site is capable receiving. The data can be
as simple as a string of text or as complex
as an list. SAS/AF components that are based on the ( ) use
characterData
a generic representation
to indicate when a character string is passed as the data
numericData
a generic representation
to indicate when numeric values are passed as the data
Legacy objects support
three default data representations, all of which provide data in a
character string:
-
_DND_TEXT for text
-
_DND_FILE for an external file
-
_DND_DATASET for a SAS table
Additional data representations enable you to drag
items from the SAS Explorer and to drop them onto a frame. These representations
include
-
EXPLORER_DATASET_NAME for SAS tables. The data is provided in a character string that contains the two-level SAS table name, such as
sasuser.fitness. -
EXPLORER_CATALOG_NAME for SAS catalogs. The data is provided in a character string that contains the two-level name, such as
sashelp.classes. -
EXPLORER_ENTRY_NAME for a specific . When the selection includes a single entry, the data is provided in a character string that contains the four-level entry name, such as
work.a.a.scl. When the selection includes two or more entries, the data is provided in a list in which each item is a character string that contains the four-level entry name. -
EXPLORER_MEMBER_NAME for multiple selections from a SAS library. When the selection includes a single entry, the data is provided in a character string that contains a two-level for catalogs or a three-level name for SAS tables (including those of type VIEW). When the selection includes two or more members, the data is provided in a list in which each item is a character string. Note that multiple selections of SAS tables or SAS catalogs are sent in an EXPLORER_MEMBER_NAME data representation.
If you create a component based on SCOM architecture, you can define your own data
representations if characterData and numericData
do not meet your needs.
A data representation is essentially a “verbal contract” between two components. As
a component developer, you must name the data representation. For example, the characterData
representation states that whatever component uses this as its drag representation,
the drag site will send a valid character value as the data. The drop site then expects
to receive a character value and can react accordingly.
It is recommended that component developers fully document their data representations
so that other developers can
know how to use them. See How the Drag and Drop Component Works for more information about the data representation.
Drop operations define actions that are performed on the data representation:
Copy is the default.
Copy
Data is provided with
no post-processing.
Link
Some mechanism synchronizes
the source and destination.
Move
Data is provided and
the source is removed.
Drag and drop operations
in SAS/AF software have
the following limitations:
-
You cannot drag objects outside the SAS environment.
-
Slider and scroll bar components do not support drag and drop operations.
-
The behavior of drag and drop operations may vary according to the host environment.
What Happens during a Drag and Drop Action
SAS/AF software performs several operations to enable drag and drop functionality between
two components. When the object is instantiated, SAS/AF checks to see whether the object's
dragEnabled or dropEnabled attributes are set to “Yes.” If either of these values is “Yes”, then: -
the object is queried for its respective
dragInfoordropInfoattribute values.-
For drag sites, SAS/AF reads the value or values of the
dragInfoattribute's dataRepresentation and invokes the _addDragRep to register each drag data representation that is supported by the object. -
For drop sites, SAS/AF reads the value or values of the
dropInfoattribute's dataRepresentation and invokes the _addDropRep method to register each drop data representation that is supported by the object.
-
-
the object is queried for its
dragOperationsand/ordropOperationssettings.-
For drag sites, the _addDragOp method is invoked to register the supported drag operations for the object.
-
For drop sites, the _addDropOp method is invoked to register the supported drop operations for the object.
-
SAS/AF permits a drop action to occur between two objects only when the two objects have
a shared data representation and a shared operation. For example, consider an object
named listbox1 that is enabled as a drag site using the characterData representation.
A second object named listbox2 is enabled
as a drop site using the characterData representation. A user can successfully complete
a drag and drop action between the two objects if they share a common operation such
as “Copy.” Objects
that do not have a matching data representation and a matching operation will not
permit a drop action to occur.
When a valid drag and drop action occurs between two objects, SAS/AF takes the value of an attribute on the drag site and sets it as the value of another
attribute on the drop site. Several methods are invoked automatically, passing an
of
sashelp.classes.DragAndDrop.class: -
The _startDrag method is invoked on the drag site. An instance of the Drag and Drop component is created.
-
The _respondToDragOnto method is invoked on a drop site as the cursor passes over a valid drop site.
-
The _respondToDragOff method is invoked on a drop site as the cursor moves off of a valid drop site.
-
The _getDragData method is invoked on the drag site after the user has released the drag item on a valid drop site. The implementation of this method prepares the data that is passed between the drag site and the drop site. It also sets the values of the appropriate attributes (including
attributeNameandattributeValue) on an instance of the Drag and Drop component before passing the object. The default implementation of _getDragData-
determines whether an
attributeNameis defined for the associated dragInfo data representation that was selected for the drop -
retrieves the current value of the named attribute and sets its name on the drag and drop object's
attributeNameattribute -
retrieves the current value for that attribute and sets the value of the drag and drop object's
attributeValueattribute
If noattributeNameis specified as part of the dragInfo data representation, then you can the _getDragData method to set the value of the drag and drop object'sattributeValueattribute. -
-
The _validateDropData method is invoked on the drop site to perform any validation that may be required.
-
The _completeDrag method is invoked on the drag site to complete any processing.
-
The _drop method is invoked on the drop site. The default implementation of the _drop method
-
retrieves the
attributeNamefrom the drop site'sdropInfoattribute based on the selected data representation -
sets the value of the attribute identified in
attributeNameusing the attributeValue that was passed in the drag and drop object
If noattributeNameexists on the drop site, you can override the _drop method and implement the desired drop behavior. -
Adding Drag and Drop Functionality to Your Components
Defining Drag and Drop Properties
For most of your applications, you will likely find it sufficient to implement drag
and drop functionality simply by setting attribute values.
You can define drag and drop properties for any component that is a subclass
of the Widget or the Frame class. To implement drag and drop, you define the drag properties of
the component that you designate as a drag site, as well as the drop properties of
another component that you want to behave as a
drop site. A component can act as both a drag site and a drop site.
The following attributes must be defined for drag sites. You might want to review
these attribute settings if you encounter problems with a drag site, or if you want
more information on a drag site's behavior.
dragEnabledsets the that determines whether the object can be dragged when selected. In many cases, setting
this attribute to “Yes” is all that is needed to implement a drag site that uses default
values for
dragInfo and dragOperations.dragInfosets the information that defines what information is transferred from the object.
The
dragInfo attribute is a list that includes a named item for each drag representation: -
the dataRepresentation, which is a name that describes the type of data that a drag site is capable of transferring. The data can be as simple as a string of text or as complex as an SCL list.
-
the attributeName, which is the name of the attribute whose value is passed to the drop site. (The drop site value is specified in the
dropInfoattribute.)
A component becomes a drag site when its data representation is defined. More than
one data representation can be defined for the drag site. When
a component is dropped onto another component, the system checks through the list
of representations for each component and chooses the first matching representation.
This matching representation enables the drag site to format the data in the required
representation. The drop site is then given its data, which it processes accordingly.
dragOperationsenables the object to indicate the action that occurs following the drag: Copy, Move,
and/or Link. By
default, an object allows the COPY action.
The following attributes must be defined for drop sites. You might want to review
these attribute settings if you encounter problems with a drop site, or want more
information on a drop site's behavior.
dropEnabledsets the state that determines whether the control can serve as a drop site. In many
cases, setting this attribute to
Yes is all
that is needed to implement a drop site using default values for dropInfo and dropOperations.dropInfosets the information that defines what information is transferred to the object. The
dropInfo attribute is a list that includes a named item for each drop representation: -
the attributeName, which is the name of the attribute whose value is set by the value of attributeName in the
dragInfoattribute. (The _setAttributeValue method is called on the drop site's attribute, using the value of the attribute specified in thedragInfoattribute.) -
the dataRepresentation, which is a name that describes the type of data that a drop site is capable of receiving. The data can be as simple as a string of text or as complex as an SCL list. It is compared to the drag site's dataRepresentation. If a match exists, the drop action occurs.More than one data representation can be defined. The last representation defined is given the highest priority.
dropOperationsdefines the drag actions that the drop site can handle: Copy, Move, and/or Link. By
default, an object allows the Copy action. In addition to the drag actions, you can
specify the associated
method that runs when the drop occurs, as well as the pop-up menu text that is displayed
for non-default drag and drop processing.
Overriding Drag and Drop Methods
SAS/AF software implements the drag and drop process by automatically executing several
methods. Although you can override these methods to add functionality, you cannot
directly call them from an SCL program.
|
Override this method...
|
To...
|
|---|---|
|
_startDrag
|
change the appearance or other state of the drag site when the drag begins. The code
that you add runs when the user begins dragging from
the drag site.
|
|
_respondToDragOnto
|
change the appearance or other state of the drop site as the dragged item passes over
it. For example, you could change the drop site's
color to indicate that a drop action is valid.
|
|
_respondToDragOff
|
change the appearance or other state of the drop site as the dragged item moves off
of the drop site. For example, you could change the
drop site back to its normal appearance if it was changed by _respondToDragOnto.
|
|
_getDragData
|
prepare the data that you want to pass to the drop site by setting attributes of the
drag and drop object that is passed between all drag and drop methods.
|
|
_validateDropData
|
perform any validation that you require before the drop action occurs. For example,
you can verify the range of data that is passed and then set the completeDrag attribute
of the drag and drop object to either “Yes” or “No” to indicate whether the drop can
occur. If completeDrag is
set to “No,” then the drop is cancelled, the _drop method does not run, and no attribute
values are set on the drop site.
|
|
_completeDrag
|
complete processing on the drag site. For example, consider two list boxes on a frame
that have the same data representation and a “Move” operation. When the item is dragged
from the first list box and dropped
onto the second, the “Move” operation indicates that the item should be removed from
the first list box. You can override _completeDrag to implement the “Move” operation
and delete the item from the drag
site.
Note: The _completeDrag method runs even if the drag and drop object's completeDrag
attribute is set to “No.” If necessary, check the value of this attribute before executing
the code.
|
|
_drop
|
process the drop action. This method executes only if the completeDrag attribute of
the drag and drop object is set to “Yes.” Typically, you override this method to perform
some action other than setting the appropriate attribute value
on the drop site. For example, you may want to display a message box that confirms
the success of
the drag and drop action.
|
How the Drag and Drop Component Works
All drag and drop methods contain signatures that accept an object as their
only argument. This object is an instance of the Drag and Drop Component (that is,
sashelp.classes.DragAndDrop.class). It provides a container for the standard drag and drop information that is passed
between a drag site and a drop site. The information is stored in the following attributes
of the Drag and Drop component:
attributeName
is the name of the attribute that is passed from the drag site to the drop site.
attributeValue
is the value of the attribute that is passed from the drag site. This attribute is
a whose type is
sashelp.classes.type.class, which contains the following attributes: | type | represents the type of the attribute value (Character, Numeric, List, Object). Based on the value of type, you can query the appropriate “value” attribute. |
| characterValue | stores the character value if type is “Character.” |
| listValue | stores the SCL list if type is “List.” |
| numericValue | stores the numeric value if type is “Numeric.” |
| objectValue | stores the object identifier if type is “Object.” |
For example, your method override could contain code as follows:
drop: public method
dndObj:input:object;
if dndObj.attributeValue.type = 'Character' then
do;
/* Retrieve dndObj.attributeValue.characterValue, */
/* then add any other code. */
end;
else if dndObj.attributeValue.type = 'Numeric' then
do;
/* Retrieve dndObj.attributeValue.numericValue, */
/* then add any other code. */
end;
/* and so forth... */
endmethod;
completeDrag
is a character attribute that you can optionally set to indicate whether a drop can
successfully occur. For
example, you can perform validation in an override of the _validateDropData method,
and you can cancel the drop action by setting this attribute to “No”. You can also
query this value in an override of the _completeDrag method to verify whether the
drop will actually occur before performing some action on the drag site.
dataOperation
is the selected drag
operation; corresponds to one of the operations specified in the
dragOperations attribute that is set on the drag site.dataRepresentation
is the form of the
data that is passed between sites; corresponds to the particular list
item in the
dragInfo attribute that is set on the drag sitedragSiteID
is the object identifier of the drag site
dragSiteLocation
indicates whether the
drag started inside or outside of the current frame
XLocation
specifies the x location of the drag site or drop site
YLocation
specifies the y location of the drag site or drop site
For components that are based on the SCOM architecture, the data specified in the
data representation (such as characterData or EXPLORER_MEMBER_NAME) is stored in the
attributeValue complex attribute of the Drag and Drop component. If one item is dragged, then the
data is stored in the characterValue attribute of the attributeValue object. If two or more items are dragged, then the
data is stored in the listValue attribute as separate character items.For complete details on the Drag and Drop component, see “SAS/AF Component Reference” in the SAS/AF online Help.
Drag and Drop Example
To demonstrate how drag and drop functionality works, consider an example that
defines two subclasses of the list
box control. The first subclass defines an object that is a drag site. The second
defines an object that is a drop site. (Of course, it is entirely possible to have
a single object that is both a drag
site and a drop site.)
To create the first
list box subclass:
-
Using the Class Editor, create a new class whose parent is
sashelp.classes.ListBox_c.classand whose description isSource List Box. -
Select the Attributes node, and then set the following values for attributes:
-
Select the dragEnabled attribute, and then right-click and select Override from the pop-up menu. Set the Initial Value to
Yes. -
Select the dragOperations attribute, and then right-click and select Override from the pop-up menu. Click the ellipsis (...) button in the Initial Value . In the dragOperations dialog box, deselect the Enabled check box for Default Copy Operation and then select the Enabled check box for Default Move Operation. Click OK to return to the Class Editor.
-
-
Save the class as
sasuser.test.SourceListBox.class. -
Select the Methods node, and then select the second _completeDrag method in the list (with the O:SASHELP.CLASSES.DRAGANDDROP.CLASS ). Right-click and select Override from the pop-up menu, and then select Source from the pop-up menu. Add the following SCL code to
sasuser.test.SourceListBox.scl:USECLASS sasuser.test.SourceListBox.class; /* Override of the _completeDrag method */ completeDrag: method dndobj:sashelp.classes.draganddrop.class; dcl num rc; /* If the rep is one that is not understood, call super. */ if ( upcase(dndobj.dataRepresentation) = 'CHARACTERDATA' ) then do; /* Check the status of the completeDrag attribute. */ if ( ( upcase(dndobj.completeDrag) = 'YES' ) AND ( upcase(dndobj.dataOperation) = 'MOVE' ) ) then do; /* Remove the selected item from the items list. */ if (selectedIndex ^= 0 ) then do; /* Delete the item from the items attribute. */ rc = delitem(items, selectedIndex ); /* Set the items attribute equal to itself to */ /* update this list box. */ items = items; end; end; end; else _super( dndobj ); endmethod; enduseclass; -
Compile and save the code, and then close the Source window.
-
Close the Class Editor.
To create the second
list box subclass:
-
Using the Class Editor, create a new class whose parent is
sashelp.classes.ListBox_c.classand whose description isTarget List Box. -
Select the Attributes node, and then set the following values for attributes:
-
Select the dropEnabled attribute, and then right-click and select Override from the pop-up menu. Set the Initial Value to
Yes. -
Select the dropInfo attribute, and then right-click and select Override from the pop-up menu. Click the ellipsis (...) button in the Value field. In the Drop Info dialog box, click Add, and then set the Drop Attribute to a blank value and the Drop Representation to
CHARACTERDATA. -
Select the dropOperations attribute, and then right-click and select Override from the pop-up menu. Click the ellipsis (...) button in the Value field. In the dropOperations dialog box, deselect the Enabled check box for Default Copy Operation and then select the Enabled check box for Default Move Operation.
-
-
Save the class as
sasuser.test.TargetListBox.class. -
Select the Methods node, and then select the second _drop method in the list (with the O:SASHELP.CLASSES.DRAGANDDROP.CLASS signature). Right-click and select Override from the pop-up menu. Select the second _validateDropData method in the list (with the O:SASHELP.CLASSES.DRAGANDDROP.CLASS signature). Right-click and select Override from the pop-up menu, and then select Source from the pop-up menu. Add the following SCL code to implement both methods in
sasuser.test.TargetListBox.scl:USECLASS sasuser.test.TargetListBox.class; /* Override of the _validateDropData method */ validateDropData: method dndobj:sashelp.classes.draganddrop.class; /* If the rep is one that is not understood, call super. */ if ( upcase(dndobj.dataRepresentation) = 'CHARACTERDATA' ) then do; /* Ensure that the type is 'Character' and that the */ /* value is not blank. If either of these checks */ /* fail, then do not let the drop happen. */ if ( ( upcase(dndobj.attributeValue.type) ^= 'CHARACTER' ) OR ^length( dndobj.attributeValue.characterValue ) ) then dndobj.completeDrag = 'No'; end; else _super( dndobj ); endmethod; /* Override of the _drop method */ drop: method dndobj:sashelp.classes.draganddrop.class; dcl num rc; /* If the rep is one that is not understood, call super. */ if ( upcase(dndobj.dataRepresentation) = 'CHARACTERDATA' ) then do; /* Ensure that the attributeValue is the correct type. */ /* If so, then insert it at the end of the items list. */ if ( upcase(dndobj.attributeValue.type) = 'CHARACTER' ) then do; dcl num rc; rc = insertc( items,dndobj.attributeValue.characterValue, -1 ); /* Set the items attribute equal to itself in order to */ /* update this list box. */ items = items; end; end; else _super( dndobj ); endmethod; enduseclass; -
Compile and save the code, and then close the Source window.
-
Close the Class Editor.
You could then use two
classes in a frame:
-
In the SAS Explorer, select File
New then select a FRAME entry. -
In the Components window, right-click and select Add Classes to add
sasuser.test.SourceListBox.classandsasuser.test.TargetListBox.class. If the Components window is not displayed when the new frame appears in the Build window, then select View
Components Window to display it. -
Drag an instance of the Source List Box object and drop it onto the frame, and then drag an instance of the Target List Box object and drop it onto the frame.
-
Select Build
Test to test the frame. Drag an item from the source list box and drop
it onto the target list box.
In the Target List Box class, the _validateDropData method verifies that the data
representation is CHARACTERDATA. Its _drop method queries the
attributeValue attribute that is passed in the drag and drop object and adds the value to its items attribute. Finally,
the _completeDrag method on the Source List Box verifies that a drop
has successfully occurred by querying the completeDrag attribute on the drag and drop object. It then removes the item
from the list of items displayed in the list box to complete the MOVE
action.Copyright © SAS Institute Inc. All Rights Reserved.
Last updated: November 4, 2019