|
|||
The Extended Documentation project is designed to explain some of the more complex tools and features in SuperCard's armoury. Thanks to the patience and skill of the authors, some of the more powerful features of SuperCard have been revealed. |
||
|
AUTHOR Chilton Webb Drag And Drop In Depth Document Revision: b3 Intro Drag and Drop is one of the most confusing aspects of Macintosh programming, but it doesn't have to be. SuperCard has gone a long way towards making it easy for anyone to add it to their application, while preserving the correct names for all of the DnD architecture's components. However, SuperCard already had drag and drop mechanisms in place before this concept became commonplace in Macintosh applications. To fully understand Drag and Drop in SuperCard, you should understand the many different ways it can be performed. The concept sounds simple enough. Dragging is something that happens when you push down on the mouse button and move the mouse. Dropping is what happens when you let go of the mouse button. And when that does nothing at all, cursing is what usually happens. In practice, both Dragging and Dropping can be performed via a variety of methods, some of which use SuperCard's internal mechanisms, some use scripts, and some use the MacOS Drag Manager. We'll start with the concept of Dragging. To drag, the user presses their button down, and moves the object by moving their mouse. There are several ways to accomplish this in SuperCard: Basic Dragging 1) Grab -- This command only works when the current tool is the Browse tool. It is very fast, fluid movement, consumes very little processor time, and stays within the confines of the current window. It can pass messages and call scripts during the move, and moves the actual object. When the grab command is complete, the target object remains in its new location unless you actively move the object back to another location. 2) Mouse Tracking -- This method is usually performed after a mouseDown or mouseStillDown command, though it can actually be used with any tool active. You simply set the location of an object to the location of the mouse, or some offset thereof, as long as the mouse is down. This method has a few downsides though. It requires more scripting than a grab command does, eats processor time. Furthermore, it does not invoke a Drag Manager, so it is also limited to its parent window. 3) Pointer tool selection -- This is what happens when you click on an object with the pointer tool. It becomes selected (the four resizing dots appear), and you can drag its outline around. If you hold down the Shift key, the movement is constrained to the x or y axis depending on where the mouse is when you press the key down. You get no events and no scripts can execute while this is happening. It consumes very little processor time. Normally this does not invoke the drag manager, so objects can't be dragged out of the window you're currently using. While we're talking about the pointer tool, I'd like to introduce you to its strange cousin, the Universal tool. Think of the Universal tool and the Pointer tool as interchangeable, with one exception. The pointer tool can only affect things on the current card or background, depending on which one you're editing. The Universal tool can affect any object on the card or background, regardless of which one you're editing. Use whichever you prefer. 4) Paint tool selection -- When editing a bitmap graphic, you can use the lasso or marquee tools (marching ants) to select a portion of the paint selection and move it around. You will see the paint object being moved around. Modifier keys can be used to alter the movement, but must be already pressed down before clicking on the object to drag it. Holding down the option key before clicking will leave a copy behind. Holding down the option and command keys will leave a 'trail' based on the edge of the graphic being moved, as it moves. The Shift key will constrain the drag to the x and y axis. Movement is limited to the area within the rectangle of the graphic you are editing. This is all handled deep inside SuperCard's internal paint routines. You get no script messages during or after this action, it uses very little processor time, and it does not use the MacOS Drag Manager. *Note: the next three options implement drag and drop via the MacOS Drag Manager, and their behavior is subject to change at Apple's whim.* 5) Pick -- this command 'lifts' the object out of SuperCard and hands it over to the MacOS Drag Manager. From there, the drag manager is in charge of deciding where it goes. The Drag Manager demands that applications not meddle with a drag, so it prevents SuperCard from being able to run scripts or receive events during a drag. This uses very little processor time. Once you've 'picked' your target, your script yields control to the Drag Manager until the object is dropped. Objects can be dragged to other locations in your window, other windows in your project, the Finder, the Desktop, and other applications. 6) Drag and Drop in text fields -- If a field has drag and drop turned on, you can drag text from it within the field, or to other fields, via the MacOS Drag Manager. This is handled by WASTE (a text engine used in SuperCard), and you have no control over the drag from script, nor do you receive any events while the drag is in progress. Text can be dragged to other fields in your window, other windows in your project, the Finder, the Desktop, and other applications. 7) Dragging via externals -- The ability to drag objects around can be supplemented via external SuperCard functions and commands. The specifics of their usage varies with each external. Basic Dropping Dropping objects, or responding to the user releasing the mouse, depends on the method used to initiate the drag. Using the same concepts for dragging, the following are the results of releasing the mouse button. 1) Grab drop -- When you release the button during a grab, the script you called 'grab' from continues and a mouseup event occurs after that. The object being dragged remains in its current (most likely new) position. If you used the 'with message' modifier to grab, you will no longer receive mousestilldown messages. If you wish to know if the object is now inside another object, you can use the 'within' command to check. If you want to know where the original drag was initiated from, you could record the rect of the object ahead of time in your script that calls grab, or use the clickloc (where it started) and mouseloc (where it ended) from a mousedown or mouseup handler to determine where you started from and how far you moved. 2) Mouse Tracking -- Identical to a grab drop, only that you can't get mousestilldown messages unless you generate them. 3) Pointer Tool drop -- If the object was initially selected with the pointer, and if you actually drag the object to a new location, you'll receive one of three messages, depending on what it is that you are dragging: dragfield, dragGraphic, or dragButton. Note that if you select an object with the pointer, but do not move the object from its location, you will not receive a drag<object type> message when you release the mouse button. 4) Paint tool drop -- The image being dragged will remain in its new location it is in when the mouse button is released. No messages are sent to you, as this is handled via SuperCard's internal paint routines. *Note: the next three options implement drag and drop via the MacOS Drag Manager, and their behavior is subject to change at Apple's whim.* 5) Pick drop -- If you used 'pick' to select the object, the MacOS Drag Manager has it at this point. SuperCard has relinquished control of it, and as such you are not guaranteed that you will receive any further messages. Furthermore, your script will not finish executing until the user releases the mouse button, regardless of where they dragged the object to. 6) Text drop -- If the text field has its allowdrag and allowdrop properties set to true, and if the allowdnd global property is set to true, text drag and drop is taken care of automatically, and you don't have to do anything additional to make it work. In addition, the WASTE engine that SuperCard uses for text will insert spacing as needed to preserve word starts and endings. 7) Externals -- Depending on what the external does, it will likely include some notes regarding how it should be used. However, script execution will still be suspended until the drag is complete. The MacOS Drag Manager That covers the basics of drag and drop. As noted above, SuperCard allows you access to the MacOS Drag Manager architecture, which will have slightly different behaviors depending on how you use it. From this point forward, for the sake of brevity, I'll refer to Drag and Drop via the MacOS Drag Manager as DnD. First, a short warning about DnD. When Apple decided this was an important enough concept to introduce system-wide, they spent a lot of time deciding how it should work. They wanted it system wide, and decided it should be consistent between all applications. The end result is that if you want your SuperCard application to work like other MacOS applications, and if you want it to cooperate with other MacOS applications, you'll pay heed to Apple's guidelines. Deciding you that know better than Apple regarding DnD will only lead to your own frustration, because while the DnD architecture is very flexible, Apple was very careful not to hand developers too much control, lest they abuse it. For more on this, see note 1 at the end of this document. On that happy note, we begin... AllowDragAndDrop and its effects At the highest level, you can toggle Drag and Drop on or off with the global variable "AllowDragAndDrop". It is set to false when SuperCard starts up. As is often the case, there are a few variations on this property's name, for those who can't remember whole words. So you can alternatively use "AllowDragNDrop" or even "AllowDnD". set the AllowDragAndDrop to true -- or false This will tell the DnD architecture that your app should be considered for a drop in the event an object in another application is dragged across your project's window. It furthermore lets SuperCard know whether or not to watch for events from the DnD architecture, and how to handle clicks and drags in your project. If you're a bit paranoid about what kind of setup your end user has, you can check 'the hasDragManager' property, which will return true or false depending on whether or not the drag manager is installed and active on their machine. The drag manager is always on in OSX. set the AllowDnD to the hasDragManager -- or the hasDragMgr, if you're yet more lazy. If the AllowDnD is set to false, the rest of this information is moot, as any other DnD relative settings are simply ignored by SuperCard. If you plan on setting the AllowDnD to true however, read on... One other setting you may be interested in is the AllowDragExport. If you plan on only allowing drag and drop within your application or project, and don't feel like sharing any of your dragged data with other apps (like the Finder), set the AllowDragExport to false. It's set to true by default, when SuperCard starts up. set the AllowDragExport to false For any given window, the behavior of drag and drop will vary first based on what tool is currently in use. If the browse tool is in use, then the contents of objects (text of a field, picturedata of a graphic, or icon of a button) in the window will be the subject of any drag, and the objects' contents become the targets for drops as well. Text dropped on a field will affect the text of that field. If the pointer tool is selected, the SuperCard object itself (the field, graphic, or button) becomes the subject of the drag, and the window becomes the target of the drop. Text dropped on a window will create a new text object in the window. It's a subtle distinction, but one worth noting. It is designed this way to keep in line with the concept of how these tools are most often used. Using the 'pick' command on a graphic with picturedata associated with it, while the tool is the browse tool, will result in a copy of that image being dragged across the window. If another graphic in a SuperCard window has its allowDrop property set to true, you can drop the image into the other graphic, resulting in the second graphic's picturedata becoming a copy of the first image's picturedata. What if you want the browse tool's drag behavior, and the drop behavior of the pointer tool? One way to make the browse tool behave somewhat more like the pointer tool is by simply setting the lockCursor to true and setting the cursor to whatever you want. For more on this technique, see note 2 at the end of this document. AllowDrag and AllowDrop Within the window, card and background objects will be treated as potential targets only if certain object-specific settings are in place. Since SuperCard is a self-modifying app, the default for all of these settings is false, so that your users can't accidentally change the text of something important by accidentally dropping a text clipping on it. There are a number of these settings, which allow you to fine tune just what can be dragged or dropped. First there's the obvious two, allowDrag and allowDrop. If an object's allowDrag is false, it can't be dragged. If it's true, it can be dragged. Clever naming convention, no? AllowDrop follows the same rules. At this point, applying what you've learned so far, how would you set up a background field and a card field so that text in the background field could be dragged into the card field? First, you'd need to set the allowDND to true. Also, set the tool to browse so that the contents of the objects are the target. The background field's allowDrag property should be set to true so that text can be moved out of it. The allowDrop of the card field must be set to true in order for it to receive the text. Lastly, in the case of fields, the lockText should be set to false for both fields. If it's set to true for the drag field, obviously you won't be able to select anything to drag it. If the locktext of the destination field is set to true, the drop will replace everything in the field instead of just inserting it. Everything else is automated by SuperCard. You don't need to do anything else for *text* drag and drop operations. Note that with the pointer tool, if you set the allowDrag of an object to true, and pick it, you will see the solid outline of the object being dragged. That's the normal DnD indicator. If the allowDrag of the object is set to false, the 'pick' command will fail, but you will still be able to drag the object around. That's because SuperCard's internal dragging system is not part of DnD. If you want to check to see whether or not the pick command worked, check 'the result' immediately after you call pick. That will return 'true' if it worked, or empty if the object could not be picked. Drag Flavors and FavoriteFlavors That's text. Text is easy. What about other types of data? Apple refers to different data types in a DnD operation as 'flavors'. By checking 'the dragFlavors' during a drop, you are able to find out what types of data are in the drop. For example, text will have a flavor of TEXT. An image can have a flavor of TIFF, JPEG, GIFf, PICT, and a slew of others. Since these flavors aren't actually defined by Apple, there's almost no end to what types of data can be the subject of a DnD operation. And since the flavors are often undocumented and application specific, with new types added all the time, you will have to get in the habit of doing some investigation to support any given favor accurately. For this reason, all of the examples below will show a bit of investigation prior to the final script. To increase the fun of DnD, some objects will have multiple types of data. Most of the time, you may only be interested in one of those types. You might only want JPEGs to be dropped in your ultra-slick JPEG tool, for instance, and the dropped data might contain JPEG, PICT, and a slew of other things like the file path and file name. In fact, you might want to filter out all files that don't contain some flavor you are looking for. To address this, SuperCard has a concept known as Favorite Flavors. It allows you much greater control over what can be dropped, and where. To use it, you first have to set the global property 'the AllowFavoriteFlavors' to true. Now any potential SuperCard object can use a 'favoriteFlavors' userproperty to filter out all drags except those that have the type of data you want. Since this is considered a 'fine tuning' setting, you have to explicitly define it for every destination object you want control over. Setting the FavoriteFlavors of an object to "TEXT", for example, will only allow drops containing TEXT payloads, even if the object is a button or graphic (which normally couldn't accept a TEXT drop). Setting an object's FavoriteFlavors userproperty to '****' (aka the wild card flavor) will allow any type of data to be dropped on it. SuperCard has a number of automatic drag and drop behaviors built in. For instance, if you drag text around in a field, it will move. If you drag an image file onto a graphic, it sets the picturedata. But sometimes you may not want this behavior. To stop these automatic flavor based behaviors, set the allowAutomaticFlavors to false. Bad Joke If you use a favoriteFlavors userproperty to bypass the default flavor settings, you will also need to handle the result of the drop yourself--SuperCard won't automatically know what to do with the dropped data if it's a flavor it doesn't understand. As a result, you will receive a MouseDrop event, which you will need to handle yourself. Note that this is different than in the real world, where you should probably not handle mouseDroppings yourself. Flavor Testing If you want to know what flavors of data an object has during a drop, set the FavoriteFlavors userproperty to the wildcard, and check 'the dragFlavors' during a drag and drop operation. You'll probably be surprised at what is actually contained in a drop, even for the simplest of drag and drop operations. For example, for a url dragged from the location bar in Safari, you might expect TEXT with a url in the data section. Here's the script we'll put in a card field (whose FavoriteFlavors userprop is set to "****")... on mouseDrop put the dragflavors into me return true end mouseDrop And now our field will have the following text in it... utf8,url ,urln,phfs,fssP,utxt,ut16,TEXT Also, it is possible that more than one object is being dropped onto your app. Once you know what flavor of data you're dealing with, you tell the drag manager which item of what flavor you're interested in, via the DragData() function. To do this, you will usually pass two parameters to DragData. The first is the item number you are after. The second is the DragFlavor. There's an exception to this, noted in note 3 at the end of this document. Example: URL Filtering So let's say you want your card field in your example project to only accept URLs. You have Safari's bookmarks open on one side of your screen, and your project window open on the other. First, make sure all of the earlier settings are still in effect, and that the allowFavoriteFlavors is set to true. Then, define a 'favoriteFlavors' userproperty for your card field, and set it to "url ". Note the space at the end of 'url'. Flavor codes are usually four characters in length, and the space in this case is important. Once you've set the userprop, you will need to handle the contents of the drop yourself. The following handler, placed in the script of the field, will do it. on mouseDrop put dragData(1,"url ") into me return true end mouseDrop You might be wondering why I returned 'true' in that handler. It's a convenience feature added by SuperCard, in this case. If you don't return anything from a MouseDrop handler, a drop will continue its automated implementation after your handler runs. For example, text will be dumped in a text field, picturedata will be set in a graphic, etc. If you return 'true', it tells SuperCard that its work is done, and that you have handled the drop operation yourself. If you return false, it will tell SuperCard that the drop was rejected (and that its work is done), and the Drag Manager will show the animation of the drag sliding off your object, back to its origin. At this point, if you drag a bookmark over to our card field, only the URL for the bookmark appears in the field. Quite magical. Since you're dropping something into a text field, you might want to know just where in the text the user tried to drop it. If you're dropping something on a text field, SuperCard simplifies your job by tacking on an additional parameter to MouseDrop, to tell you where in the text the drop occurred. So you could use this variation on our earlier script to implement this... on mouseDrop xOffset put dragData(1,"url ") after char xOffset of me return true end mouseDrop Example: A graphic dragged from a browser Again, we're dealing with text data here. And again, that's pretty simple stuff. Let's move on to graphics. Graphics, in SuperCard, can contain pictureData. Let's say you have two draw graphics. The first one has a picturedata, and its allowDrag set to true. The second has its allowdrop set to true, but no picturedata. If the tool is set to the pointer tool (or universal tool, or the button tool), dragging the first graphic will only serve to move the graphic. If the tool is the browse tool, dragging will set the picturedata of the second graphic to the picturedata of the first graphic. Additionally, dragging from the first graphic to another application will drop the image into the other application. And that's all done automatically! Let's say you want to display images that are dropped from a web browser, into your project. Since we don't know what types of data that might be, we'll create a graphic, define and set its favoriteflavors to "****", set its allowdrop to true, choose the browse tool, and give it the following script... on mousedrop put the dragflavors return true end mousedrop Now, we drop our Safari image. What do we get? TIFF,rtfd,url ,urln,utf8,PICT,phfs,fssP,utxt,ut16,TEXT Of those, we know that PictureData can display PICT, so that's what we'll use in our script. And we're no longer interested in the other flavors, so we can change the Wildcard to PICT, and change the script to the following... on mousedrop get dragData(1,"PICT") set the picturedata of me to display it return true end mousedrop Now when we drop a picture from a web browser onto our graphic, it appears as though the graphic was actually moved to our application. It was, in a roundabout manner, but the user doesn't need to know this. Here's a neat trick--create a draw text graphic (it has to be a draw *text* graphic), set the favoriteFlavors to 'url ', and put the following script in it. on mousedrop set the picturedata of me to display dragData(1,"PICT") set the textdata of me to dragData(1,"url ") return true end mousedrop Now when you drop an image from a website onto your graphic, you'll get the url to the graphic in the text part of the SC object, and the picturedata of the new SC object will be the image you dropped on it. Example: Dragging files from the Finder The one place most people are most familiar with DnD is the Finder. So let's say you want to have a 'path box', where users can drag their file, and have the path to the file magically appear in the text box. Again, we go back to our original text field concept, set its favoriteFlavors to "****", and use this script... on mouseDrop put the dragflavors into me return true end mouseDrop Drag a file onto it from the Finder, and your field will have (depending on the version of the OS you are using)... furl,from,hfs What you may not see here is that there is a space after "hfs". So it's really "hfs ". These aren't really documented anywhere, so depending on the data you're after, you may need to experiment a bit. In this case, we have it easy. "hfs " is the dragFlavor we're after. So we set our favoriteFlavors to "hfs ", to ensure that our drop will at least contain that, and then use the following script... on mouseDrop put dragData(1,"hfs ") into me return true end mouseDrop And now, when a file is dragged onto your field, it will have the path to the file in question. But what is that "furl" flavor? Let's find out! Change the script thusly... on mouseDrop put dragData(1,"furl") into me return true end mouseDrop And now you get a 'file url', it appears. In my case, file://localhost/Users/chilton/Desktop/fakefile.txt You could use that if you're going to deal with these dropped files via the shell() function, which requires Unix paths. And there's one more, "from", which only appears in Finder drags in some versions of OSX. At this time there isn't much information about what this is, so it's being ignored for now. Example: Filtering only certain folders from a Finder drag Let's say you wanted to allow only certain files or folders to be dragged onto your SC object. Here's a script that does it. on mouseDrop global gFolder get dragData(1,"hfs ") if gFolder is not in it then -- it's not in the path return false else -- it is in the path put it into me return true end if end mouseDrop As you can see, returning 'false' from a mouseDrop handler will return the drag to its origin. Example: Filtering only drives from a Finder drag A seldom used relative to the FavoriteFlavors userproperty is the FavoriteHFSFlavors userproperty. Creating a user property by this name will allow you to filter only files with the file types listed in the userproperty. Additionally, it can be used with the 'disk' type to filter out all but disks. To use this, define a 'FavoriteHFSFlavors' userproperty for the target object, and set it to "disk". set the FavoriteHFSFlavors of cd fld 1 to "disk" Example: Graphic picturedata to button picturedata Let's say you want to drag the picturedata from a graphic to an imagewell button. There's no automatic way to do this, so let's use our original script again to do a bit of exploration. Using our earlier two graphic setup, create a new imagewell button, set its allowdrop to true, set its favoriteFlavors to the wildcard, and set its script to this... on mousedrop put the dragflavors end mousedrop Now choose the browse tool, and drag the picturedata from one graphic onto the button. The following is dumped in the messagebox... MDOX,PICT,TEXT,styl ... eeenteresting. Looks like there's a PICT in there, which could be expected. TEXT and styl are the result of the source graphic being a draw text graphic we created earlier. But what is this MDOX? Changing the script to the following... on mousedrop put dragdata(1,"MDOX") return true end mousedrop ... and if I drag that graphic again, I get the following text in the messagebox... card graphic ID 156 of card ID 104 of window ID 100 of (... and a bunch more text) So the MDOX flavor returns the descriptor of the object being dragged! Back to the challenge at hand, with this new information, there are a few ways we could do this. We could set it to display the PICT data, easily enough, but we did that earlier. So let's try fiddling with the original graphic. on mousedrop get dragdata(1,"MDOX") export picturedata of it into x set the picturedata of me to display x return true end mousedrop It's possible some moron might drag a button or text or something onto our graphic, thereby creating a script error. Time for some defensive scripting... on mousedrop get dragdata(1,"MDOX") if the kind of it is "graphic" then export picturedata of it into x set the picturedata of me to display x return true else return false end if end mousedrop Another way to handle this is to check the DragObject inside the mouseDrop handler, which will return the same info as the MDOX dragData. Pointer tool mode This will allow only graphics to be dragged onto our target. All others will be refused. You probably noticed that so far, most of the examples have been performed while the tool is the browse tool. If you set the tool to pointer, another set of behaviors will occur. So go on, set the tool to pointer. Now, in the script for the graphic above, add this to the script... on pointerdown pick me pass pointerdown end pointerdown You might notice that if you drag the object now, it refuses to stay where you move it, if you drop it in the same window you're in. And if you drag it to another application, it won't drop it there either. That's the correct behavior in this case, because of two things. First, SuperCard objects themselves have no meaning outside of SuperCard and other SC applications. Dragging a button to a browser, for example, would make no sense. Second, there is already an existing mechanism for click and dragging objects around in SuperCard. If you really want to track the movement of objects with the pointer tool, you can check DragButton, DragField, and DragGraphic, depending on what object was moved. One of these messages will be sent to any object dragged with the pointer tool as long as you didn't use 'pick' to initiate the drag. Tracking the movement of the mouse during a DnD operation is expensive from a processor standpoint, and the DnD implementation was put into SuperCard long before Apple made whatever fancy   Mac you're reading this on. So this mechanism is purely for dragging objects from one window into another SC window, where a copy of the button, field, or graphic, will be placed. However, there is an operation not handled in SuperCard that was addressed by DnD, so it was added to SC bag of tricks. Option+clicking an object will duplicate a button when you drop it, even if you drop it in the source window. So let's change it to the following to make things a bit more useful. on pointerdown if the optionkey is down then pick me pass pointerdown end pointerdown To intercept a drop while in pointer mode, you have to put the mousedrop script in the card script, and set the FavoriteFlavors (if needed) at the card level as well, because the entire window becomes a target for the drop, not just the objects within it. Put the following code in your window script. on mousedrop put dragData(1,"MDOX") return true end mousedrop The default action for the pointer tool is to drag objects around. Option+dragging an object with the above script will duplicate the object, using an internal routine. However, this is a special case (option+dragging a picked object). Example: Visual Bookmark system Here's a way to use all of the above concepts to create a drag and drop 'scrapbook' program. One issue here is that an image may not come from a browser. If it is dragged into our project from the Finder, no PICT or JPEG data may be available. So to get around this, we're going to check to see if it's coming from the Finder, and if it is, we'll check to see if it's a type we know about. If that holds true, we'll set our picturedata up accordingly. If it turns out to be a url, and if it has a PICT or JPEG data attached as well, we'll use that info for our graphic. Also, we want roughly in the same place the user wants to put it, so make sure you set the location of the new graphic to globalloc(the mouseLoc), which will be the location of the mouse when the drop is made. To begin, set the tool to pointer, and define a favoriteFlavors userproperty for the card, named "****". Now add this script in the card script... on mousedrop put the dragflavors into theFlavors put empty into theImage put empty into theOrigin
if "url " is in theFlavors then put dragData(1,"url ") into theOrigin if "PICT" is in theFlavors then put dragData(1,"PICT") into theImage else if "JPEG" is in theFlavors then put dragData(1,"JPEG") into theImage else return false end if else if "hfs " is in theFlavors then put dragData(1,"hfs ") into theOrigin if "PICT" is in theFlavors then put dragData(1,"PICT") into theImage else put empty into theImage end if
end if
lock screen new grc define "originalloc" of last cd grc set the originalloc of last cd grc to theOrigin
if theImage is empty then set the picturedata of last cd grc to file theOrigin else set the picturedata of last cd grc to display theImage end if
set the loc of last cd grc to globalloc(the mouseloc) unlock screen
return true end mousedrop Then, to round things out, add the next script and command+clicking on an image with the pointer tool will take you to the original file. Depending on what version of the MacOS you're using, you may want to modify the GURLGURL line, as that may not work in yours. See note 4 at the end of this document for additional suggestions. on pointerdown if the commandkey is down then get the originalLoc of the target if char 1 to 4 of it is "http" then send the originalloc of the target to program "Finder" with "GURLGURL" else send the originalloc of the target to program "Finder" with "aevtopen" end if end if end pointerdown Multiple drag objects This works well enough for a single object. But what if you drag more than one file into your project's window? Simple! You get more than one line of text in the DragFlavors. The following script, when placed in a text field's script, will list the names of every file dropped on it. on mousedrop get the dragflavors put empty into x repeat with n = 1 to the number of lines of it if "hfs " is in line n of it then put dragData(n,"hfs ") & cr after x end if end repeat put x into me return true end mousedrop In SuperCard 4.5, fields can contain objects. This is a new addition, and adds one more piece to this ever growing puzzle. To use field objects, you have to set the allowObjects for the field to true. Then, when a new object is created in the field (say, by a drag and drop operation), a NewFieldObject will be created. If you want to trap that, you can use this script... on NewFieldObject theLoc put theLoc end NewFieldObject Summary The concept of Drag and Drop is not as simple as it seems. Hopefully it's a bit clearer now, and you know how to investigate dragged objects to see how they can be used. There's a checklist at the bottom of this document for making sure that DnD is operational in your project or application. for more information, look up allowDragAndDrop in the Language guide. ----- Additional Notes Note 1) For instance, your application is not allowed to change the contents of a drag while it is being dragged. It is not allowed to intercept drops meant for other applications. It can alter the location of the cursor during a drag, but it's not usually a good idea. And above all else, your project or application is not allowed to switch to the foreground while a drop is in progress. It can during a drag, but once the user has released the mouse button, your app must complete its work and return true or false before switching contexts. Note 2) If you want to simulate the behavior of the pointer tool while using the browse tool, you can place a large graphic in the background, set its FavoriteFlavors to wildcard, and use the mouseloc to dump data roughly where it was dropped. By doing so, you prevent users from being able to resize objects in your window, and it gives you the ability to set the boundaries for the drop zone. You might want to set the lockcursor to true, and set the cursor to arrow at some point as well. To add a bit more flair, you could use the objectCursor to provide special case cursors for the different zones in your app. Fore more on objectCursors, look up allowObjectCursors in the language guide. Note 3) If you're dealing with the 'hfs ' dataFlavor, a third parameter to dragData can be used to obtain the filetype of a file being dragged in, if it's an 'hfs ' drag. Normally, dragData would return a path. However, you can pass it "path" or "type" as an optional third parameter. If you use "type", you will be given the creator and file type of the data at this file location. Example: get dragData(1,"hfs ","path") -- returns "Macintosh HD:Apple Panther2", which is the path. Example: get dragData(1,"hfs ","type") -- returns "clpp,drag", which is creator, file type Note 4) There are a number of different methods you can use to ensure that the url or file path gets launched in the appropriate browser. For example, there's the LaunchURLX external that will use the appropriate method based on the OS it is running on. Or you could do this with AppleEvents as shown. This can be handled as well by replacing 'theURL' with the url in question, in the following snippet... get Script(do, Applescript, merge("open location `[[theURL]]`") ) Checklist for Drag And Drop -- This is a basic overview of what needs to be set -- in order for a drag or drop to be completed. 1) set the AllowDnD to the hasDragMgr 2) set the AllowFavoriteFlavors to true -- optional, default is false 3) set the AllowAutomaticFlavors to false -- optional, default is true 4a) the tool is the Pointer tool i) set the allowDrag of the source objects to true as needed ii) set the favoriteFlavors of the card, background, or window -- optional iii) set the favoriteHFSFlavors of the card, background, or window -- optional iii) place your mouseDrop handler in the cd, bg, or wd scripts if needed iv) use the 'pick' command to initiate drags out of the window, or to duplicate. 4b) the tool is the Browse tool i) set the allowDrag and allowDrop of the source objects to true as needed ii) set the favoriteFlavors of the drop target objects -- optional iii) set the favoriteHFSFlavors of the drop target objects -- optional iii) place your mousedrop handlers in the drop target objects as needed iv) use the 'pick' command to grab the contents of objects. 4c) You want field objects i) set the allowObjects of cd fld <descriptor> to true ii) set the favoriteFlavors of the drop target -- optional iii) Don't intercept the mousedrop handler, or pass mousedrop 5) Clicky-clicky |
||