home *** CD-ROM | disk | FTP | other *** search
- /* DirPanel
- *
- * A category of SavePanel that extends SavePanel's capabilities
- * to specifying directories instead of files.
- *
- * Copyright 1991, 1992 Scott Hess. This source code may be
- * redistributed and modified without restriction. Well, one
- * restriction - do not claim that you wrote it.
- *
- * Scott Hess
- * 12901 Upton Avenue South, #326
- * Burnsville, MN 55337
- * (612) 895-1208
- * scott@gac.edu
- * shess@ssesco.com
- */
- #import "DirPanel.h"
- #import <appkit/Button.h>
- #import <appkit/Form.h>
- #import <appkit/NXBrowser.h>
- #import <appkit/OpenPanel.h>
-
- @implementation SavePanel (DirPanel)
-
- /* This flags a real cancel. */
- static BOOL notCancel=NO;
-
- /* This is where the real okButton is stored. */
- static id realOkButton=nil;
-
- /* When we are masquerading as the okButton, catch setEnabled:.
- * Always leave the okButton enabled.
- */
- - setEnabled:(BOOL)flag
- {
- [realOkButton setEnabled:YES];
- return self;
- }
-
- /* All other methods are forwarded to Button.
- * I'm assuming that the right Button methods make it through. If
- * it relies on responder chains and stuff, though, I'm probably
- * sunk. In any case, it does seem to work, which is all I ask.
- */
- - forward:(SEL)aSelector :(marg_list)argFrame
- {
- if( [realOkButton respondsTo:aSelector]) {
- return [realOkButton performv:aSelector :argFrame];
- }
- return [self doesNotRecognize:aSelector];
- }
-
- /* Call this just like runModal.
- */
- -(int)dirPanelRunModal
- {
- int ret;
- /* Store the okButton target/action. */
- id okt=[okButton target];
- SEL oka=[okButton action];
-
- /* Store the browser target/action. */
- id browsert=[browser target];
- SEL browsera=[browser action];
- SEL browserda=[browser doubleAction];
-
- /* Enable the button, and redirect it at realOk:. */
- [okButton setEnabled:YES];
- [okButton setTarget:self];
- [okButton setAction:@selector( realOk:)];
-
- /* Redirect the browser. */
- [browser setTarget:self];
- [browser setDoubleAction:@selector( realOk:)];
- [browser setAction:NULL];
-
- /* Force to reload the browser. Otherwise, it might come
- * up with no visible selection (the selection sometimes
- * scrolled out of view to the left).
- */
- [browser loadColumnZero];
-
- /*store away the okButton, and "become" it. */
- realOkButton=okButton;
- okButton=self;
-
- /* Make sure we don't misfire on this. */
- notCancel=NO;
-
- /* OpenPanel doesn't seem to pay attention to setRequiredFileType,
- * so I have to do things differently for it. Actually, I
- * would tend to recommend just using SavePanels, but that's
- * just me.
- *
- * The idea, here, is that not many people are going to
- * have files named *.abcdefghijklmnop, so the SavePanel
- * can't find any, so it can only show directories, that
- * you can move around in and look for stuff. Since we're
- * choosing directories, this is the right behaviour.
- */
- if( [self isMemberOf:[SavePanel class]]) {
- [self setRequiredFileType:"abcdefghijklmnop"];
- ret=[self runModal];
- } else {
- const char *types[]={ "abcdefghijklmnop", NULL};
- /* I cast to OpenPanel to remove the warning on compile. */
- ret=[(OpenPanel *)self runModalForTypes:types];
- }
-
- /* If SavePanel thinks we canceled, check to see if _we_
- * think so, too.
- */
- if( !ret && notCancel) {
- notCancel=NO;
- ret=YES;
- }
-
- /* Restore the okButton's target/action. */
- okButton=realOkButton;
- [okButton setTarget:okt];
- [okButton setAction:oka];
-
- /* Restore the browser's original target/action. */
- [browser setTarget:browsert];
- [browser setAction:browsera];
- [browser setDoubleAction:browserda];
- return ret;
- }
- /* Handles ok's for the panel. I need to pretend to be a cancel,
- * for some reason. Don't ask me - it wasn't working when I didn't
- * do it, so I left it.
- */
- - realOk:sender
- {
- const char *formValue=[form stringValueAt:0];
- if( [sender isKindOf:[NXBrowser class]]) {
- /* Causes a visible "bounce" for the okButton, along with
- * running this action.
- */
- return [okButton performClick:sender];
- }
-
- /* If there's data in the form, then don't exit. */
- if( !formValue || !*formValue) {
- /* Mark this as a fake Cancel. */
- notCancel=YES;
-
- /* Use the ok: method to pull out any data from the form. */
- [self ok:sender];
-
- /* Use cancel: to get out of the modal loop. */
- return [self cancel:sender];
- } else {
- /* Both of these methods may draw, so flush all at once. */
- [self disableFlushWindow];
-
- /* Aquire the data from the form. */
- [self ok:sender];
-
- /* Make certain that the lastColumn's selection is visible.
- * Consider typing "..". Without this code, it could
- * ".." right off the left hand side of the browser, and
- * there would be no visible selection and the right hand
- * column would be blank.
- */
- if( [browser numVisibleColumns]>1) {
- [browser scrollColumnToVisible:[browser lastColumn]-1];
- }
-
- [self reenableFlushWindow];
- [self flushWindowIfNeeded];
- return self;
- }
- }
- @end
-