jb@aries5.uucp (10/31/89)
Has anybody written a SFGetFolder/SFPutFolder routine -- What I want to be able to do is select or create a folder in a nice manner. The problem that I have with the implementations that I have seen of selecting a folder i.e. 'Set Transfer Directory...' in Telnet is that it is not intuitive whether I am selecting the directory of the folder that is hilighted or the directory that I am currently in. Even if you do not have any code to do this, I am interested in feedback on the area of user interface. If there is enough interest I will summarize results. Thanks in advance Jim Bruyn
oster@dewey.soe.berkeley.edu (David Phillip Oster) (11/01/89)
Tim Maroney posted some nice suggestions about selecteing folders a while back, and TOPs seems to have a decent user interface for this. Remember, you need to handle non-HFS volumes such as 400k floppies, and you need to let the user select the entire drive on HFS volumes. The latter requirement makes it hard to just point at a folder in SFGetFile() and say "that's the one", since drivers aren't listable in the scrollbale part of SFGetFile().
lsr@Apple.COM (Larry Rosenstein) (11/01/89)
DTS Sample Code #18 shows all the wonderful things you can do with Std File, including selecting directories. I think they implement the same interface that MPW uses for its 'GetFilename -d' command. Larry Rosenstein, Apple Computer, Inc. Object Specialist Internet: lsr@Apple.com UUCP: {nsc, sun}!apple!lsr AppleLink: Rosenstein1
6600pete@hub.UUCP (11/01/89)
From article <32277@ucbvax.BERKELEY.EDU>, by oster@dewey.soe.berkeley.edu (David Phillip Oster): > ...you need to > let the user select the entire drive on HFS volumes. The latter > requirement makes it hard to just point at a folder in SFGetFile() and say > "that's the one", since drivers aren't listable in the scrollbale part of > SFGetFile(). StuffIt allows you to select entire volumes by making sure nothing is selected in the file list. I suppose this is done by scrolling to the bottom of the list and clicking the blank space at the bottom. This is not intuitive, though. Maybe it's time someone reqqrote Standard File and released the code to the PD. (Or maybe we should just wait for System 8.0, which may (or may not) unify the Desktop metaphor and Standard File.) Pete Gontier : pete@cavevax.ucsb.edu; outgoing .UUCP addresses bounce Editor, Macker : Online Macintosh Programming Journal; mail for subscription Hire this kid : Mac, DOS, C, Pascal, asm, excellent communication skills Underground : Internet BBS via rlogin 128.11.41.100 -l bbs
tim@hoptoad.uucp (Tim Maroney) (11/01/89)
In article <709@maytag.waterloo.edu> jb@aries5.UUCP () writes: >Has anybody written a SFGetFolder/SFPutFolder routine -- What I want to be > able to do is select or create a folder in a nice manner. This is the second most common question here, after "How do I get a full file name?" Apple, are you listening? How about a couple of new traps in System 7.0? Anyway, the answer is yes. LSC source code at end of message. >The problem that I have with the implementations that I have seen of >selecting a folder i.e. 'Set Transfer Directory...' in Telnet is that it >is not intuitive whether I am selecting the directory of the folder >that is hilighted or the directory that I am currently in. That's very perceptive. The solution is not to allow the user to click on the "Use Folder" (or whatever) button when a folder is selected, and to put a sentence in the dialog explaining which folder is being dealt with just to make sure there's no confusion. Hardly anyone does this in practice, but everyone should. Here goes with the code. static Boolean good, noSys, needWrite, allowFloppy, allowDesktop; static SFReply reply; pascal Boolean FolderFilter(pb) FileParam *pb; { return true; } pascal short FolderItems(item, dlog) short item; DialogPtr dlog; { if (item == 2) { good = true; item = 3; } return item; } pascal void FolderEvents(dialog, event, item) DialogPtr dialog; EventRecord *event; short *item; { ControlHandle ch; short type; Rect r; HVolumeParam vp; /* disable if a directory is selected in the list */ GetDItem(dialog, 2, &type, &ch, &r); if (reply.fType) { HiliteControl(ch, 255); return; } /* get information on the volume */ vp.ioNamePtr = (StringPtr)0; vp.ioVRefNum = -SFSaveDisk; vp.ioVolIndex = 0; if (PBHGetVInfo(&vp, false)) HiliteControl(ch, 255); else if (vp.ioVSigWord != 0x4244) /* HFS? */ HiliteControl(ch, 255); else if (vp.ioVDRefNum >= 0 || vp.ioVDrvInfo == 0) /* ejected? */ HiliteControl(ch, 255); else if (needWrite && (vp.ioVAtrb & 0x8080)) /* locked? */ HiliteControl(ch, 255); else if (!allowFloppy && vp.ioVDRefNum == -5) /* floppy? */ HiliteControl(ch, 255); else if (!allowDesktop && CurDirStore == 2) /* desktop? */ HiliteControl(ch, 255); else if (noSys && CurDirStore == vp.ioVFndrInfo[0]) /* blessed? */ HiliteControl(ch, 255); else HiliteControl(ch, 0); } GetFolder(name, volume, folder, writeable, system, floppy, desktop) char *name; short *volume; long *folder; Boolean writeable, system, floppy, desktop; { short oldvol = -SFSaveDisk; long oldfolder = CurDirStore; Point where; SetPt(&where, 55, 55); good = false; if (*volume && *folder) { SFSaveDisk = -*volume; CurDirStore = *folder; } needWrite = writeable, noSys = !system, allowFloppy = floppy; allowDesktop = desktop; SFPGetFile(where, (char *)0, FolderFilter, -1, 0, FolderItems, &reply, 14, FolderEvents); if (!good) return false; *volume = -SFSaveDisk; *folder = CurDirStore; FullFileName(name, "", -SFSaveDisk, CurDirStore); SFSaveDisk = -oldvol; CurDirStore = oldfolder; return true; } Note -- you need dialog 14 for this to work. This is a slightly hacked version of Standard File. Here's a Rez listing made by DeRez: resource 'DLOG' (14, "Standard File for a Folder") { {55, 78, 312, 439}, dBoxProc, invisible, noGoAway, 0x0, 14, "" }; resource 'DITL' (14, "Standard File for a Folder") { { /* array DITLarray: 11 elements */ /* [1] */ {33, 507, 51, 587}, Button { enabled, "Open" }, /* [2] */ {135, 256, 153, 336}, Button { enabled, "Use Folder" }, /* [3] */ {161, 256, 179, 336}, Button { enabled, "Cancel" }, /* [4] */ {40, 247, 62, 348}, UserItem { disabled }, /* [5] */ {69, 256, 87, 336}, Button { enabled, "Eject" }, /* [6] */ {95, 256, 113, 336}, Button { enabled, "Drive" }, /* [7] */ {40, 15, 185, 246}, UserItem { enabled }, /* [8] */ {40, 229, 185, 246}, UserItem { enabled }, /* [9] */ {124, 251, 125, 339}, UserItem { disabled }, /* [10] */ {97, 606, 198, 702}, StaticText { disabled, "" }, /* [11] */ {196, 15, 246, 345}, StaticText { disabled, "Move until ^0 is shown in the small rect" "angle at the top, above the list of file" "s and folders. Then click \"Use Folder\"." } } }; The "^0" is filled in by the caller of GetFolder, using ParamText. Granted, that's not the cleanest solution, but GetFolder already has too many parameters. If you are only using this for one thing in your software, then you can always just fill it in in the dialog item in the resource file instead. No flames from symbolic-constant freaks. It's just as easy to change a number in a routine as it is to change it in #defines, if it only appears once. And the dialog items are not going to change; their order is mandated by Standard File. I do apologize for the use of globals, but as all Standard File hackers know, the system doesn't give you the ability to do without them easily. If your filter procs were passed a pointer to the reply record, you could embed it in a structure and use its pointer as a structure pointer, but it doesn't get passed. And touching the dialog refCon causes an explosion. If you really can't cope with globals, you're stuck with using a button refCon or something, and that's a bit of a mess. (Also, I don't think I'd figured out that kind of devious solution back when I wrote this.) The one great omission in this code is a "New" button. One day I'll get around to adding it. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com FROM THE FOOL FILE: "Women's wages are 56% of men's -- but that's not necessarily evidence of discrimination in employment." -- Clayton Cramer in news.groups and soc.women
jtn@zodiac.ADS.COM (John Nelson) (11/10/89)
In article <709@maytag.waterloo.edu> jb@aries5.UUCP () writes: >Has anybody written a SFGetFolder/SFPutFolder routine -- What I want to be > able to do is select or create a folder in a nice manner. > >The problem that I have with the implementations that I have seen of >selecting a folder i.e. 'Set Transfer Directory...' I'm writing an application that basically does just this, however it doesn't consist of one function call. You have to write a filter function for SFPGetFile to handle the directories and some parameter block routines to stat the files to see if they're files or folders. It isn't finished yet so I really don't know if it can be done this way or not. I'll let you all know what happens when it is done. John T. Nelson UUCP: sun!sundc!potomac!jtn Advanced Decision Systems Internet: jtn@potomac.ads.com 1500 Wilson Blvd #512; Arlington, VA 22209-2401 (703) 243-1611
keith@Apple.COM (Keith Rollin) (11/15/89)
In article <9741@zodiac.ADS.COM> jtn@ads.com (John Nelson) writes: >In article <709@maytag.waterloo.edu> jb@aries5.UUCP () writes: >>Has anybody written a SFGetFolder/SFPutFolder routine -- What I want to be >> able to do is select or create a folder in a nice manner. >> >>The problem that I have with the implementations that I have seen of >>selecting a folder i.e. 'Set Transfer Directory...' MacDTS has released a sample program that shows you how to do this, among other tricks with StdFile. You can get this from APDA, BBS's and finer FTP sites everywhere, including ours. Basically, it involves writing a file filter procedure that always returns TRUE. Here is the relevant code: FUNCTION FoldersOnly(p:ParmBlkPtr):BOOLEAN; { Normally, folders are ALWAYS shown, and aren't even passed to } { this file filter for judgement. Under such circumstances, it is } { only necessary to blindly return TRUE (allow no files whatsoever). } { However, Standard File is not documented in such a manner, and } { this feature may not be TRUE in the future. Therefore, we DO check } { to see if the entry passed to us describes a file or a directory. } BEGIN FoldersOnly := TRUE; IF BTst(p^.ioFlAttrib,4) THEN FoldersOnly := FALSE; END; Hope this helps, -- ------------------------------------------------------------------------------ Keith Rollin --- Apple Computer, Inc. --- Developer Technical Support INTERNET: keith@apple.com UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith "Argue for your Apple, and sure enough, it's yours" - Keith Rollin, Contusions
silverio@brahms.berkeley.edu (C J Silverio) (11/15/89)
jb@aries5 asks: Has anybody written a SFGetFolder/SFPutFolder routine -- What I want to be able to do is select or create a folder in a nice manner. Keith Rollin, Apple DTS whipping boy, kindly replies: MacDTS has released a sample program that shows you how to do this, among other tricks with StdFile. You can get this from APDA, BBS's and finer FTP sites everywhere, including ours. Here's the rough plan for FTP'ing the stuff from Apple.com. Remember to be courteous about hogging resources. Also, there is so much code (over 2 Megs unstuffed) that it might be cheaper and easier to buy it from APDA. I haven't had much time to look at all the code, but it seems really helpful. I only had one system crash (a good one!) in the whole pile. 1 ftp apple.com as anonymous, supply userid as password. 2 cd /pub/dts/mac/sc. 3 get files like unto a crazy person. 4 Use Stuffit! to upack all this. The stuffed files require 3 800K floppies. At 1200 baud, this will take 70 quadrillion years (subjective time) to download. Thanks, Apple DTS, for supplying this bounty. It's half of what I need to be a good Mac programmer.
tim@hoptoad.uucp (Tim Maroney) (11/16/89)
I entered complete source code to do this here. So far, I have not received any responses, and the discussion has proceeded without reference to this source code. Did it get out? -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com Feminism that refuses to use the word "patriarchy" is kin to abolitionism that refuses to use the word "slavery".