home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / Classes / DirPanel / DirPanel.m < prev    next >
Text File  |  1992-07-09  |  5KB  |  176 lines

  1. /* DirPanel
  2.  *
  3.  * A category of SavePanel that extends SavePanel's capabilities
  4.  * to specifying directories instead of files.
  5.  *
  6.  * Copyright 1991, 1992 Scott Hess.  This source code may be
  7.  * redistributed and modified without restriction.  Well, one
  8.  * restriction - do not claim that you wrote it.
  9.  *
  10.  * Scott Hess
  11.  * 12901 Upton Avenue South, #326
  12.  * Burnsville, MN  55337
  13.  * (612) 895-1208
  14.  * scott@gac.edu
  15.  * shess@ssesco.com
  16.  */
  17. #import "DirPanel.h"
  18. #import <appkit/Button.h>
  19. #import <appkit/Form.h>
  20. #import <appkit/NXBrowser.h>
  21. #import <appkit/OpenPanel.h>
  22.  
  23. @implementation SavePanel (DirPanel)
  24.  
  25. /* This flags a real cancel. */
  26. static BOOL notCancel=NO;
  27.  
  28. /* This is where the real okButton is stored. */
  29. static id realOkButton=nil;
  30.  
  31. /* When we are masquerading as the okButton, catch setEnabled:.
  32.  * Always leave the okButton enabled.
  33.  */
  34. - setEnabled:(BOOL)flag
  35. {
  36.     [realOkButton setEnabled:YES];
  37.     return self;
  38. }
  39.  
  40. /* All other methods are forwarded to Button.
  41.  * I'm assuming that the right Button methods make it through.  If
  42.  * it relies on responder chains and stuff, though, I'm probably
  43.  * sunk.  In any case, it does seem to work, which is all I ask.
  44.  */
  45. - forward:(SEL)aSelector :(marg_list)argFrame
  46. {
  47.     if( [realOkButton respondsTo:aSelector]) {
  48.         return [realOkButton performv:aSelector :argFrame];
  49.     }
  50.     return [self doesNotRecognize:aSelector];
  51. }
  52.  
  53. /* Call this just like runModal.
  54.  */
  55. -(int)dirPanelRunModal
  56. {
  57.     int ret;
  58.       /* Store the okButton target/action. */
  59.     id okt=[okButton target];
  60.     SEL oka=[okButton action];
  61.     
  62.     /* Store the browser target/action. */
  63.     id browsert=[browser target];
  64.     SEL browsera=[browser action];
  65.     SEL browserda=[browser doubleAction];
  66.     
  67.       /* Enable the button, and redirect it at realOk:. */
  68.     [okButton setEnabled:YES];
  69.     [okButton setTarget:self];
  70.     [okButton setAction:@selector( realOk:)];
  71.     
  72.     /* Redirect the browser. */
  73.     [browser setTarget:self];
  74.     [browser setDoubleAction:@selector( realOk:)];
  75.     [browser setAction:NULL];
  76.     
  77.     /* Force to reload the browser.  Otherwise, it might come
  78.      * up with no visible selection (the selection sometimes
  79.      * scrolled out of view to the left).
  80.      */
  81.     [browser loadColumnZero];
  82.     
  83.         /*store away the okButton, and "become" it. */
  84.     realOkButton=okButton;
  85.     okButton=self;
  86.     
  87.       /* Make sure we don't misfire on this. */
  88.     notCancel=NO;
  89.     
  90.     /* OpenPanel doesn't seem to pay attention to setRequiredFileType,
  91.      * so I have to do things differently for it.  Actually, I
  92.      * would tend to recommend just using SavePanels, but that's
  93.      * just me.
  94.      *
  95.      * The idea, here, is that not many people are going to
  96.      * have files named *.abcdefghijklmnop, so the SavePanel
  97.      * can't find any, so it can only show directories, that
  98.      * you can move around in and look for stuff.  Since we're
  99.      * choosing directories, this is the right behaviour.
  100.      */
  101.     if( [self isMemberOf:[SavePanel class]]) {
  102.     [self setRequiredFileType:"abcdefghijklmnop"];
  103.     ret=[self runModal];
  104.     } else {
  105.     const char *types[]={ "abcdefghijklmnop", NULL};
  106.         /* I cast to OpenPanel to remove the warning on compile. */
  107.     ret=[(OpenPanel *)self runModalForTypes:types];
  108.     }
  109.     
  110.     /* If SavePanel thinks we canceled, check to see if _we_
  111.      * think so, too.
  112.      */
  113.     if( !ret && notCancel) {
  114.     notCancel=NO;
  115.     ret=YES;
  116.     }
  117.     
  118.         /* Restore the okButton's target/action. */
  119.     okButton=realOkButton;
  120.     [okButton setTarget:okt];
  121.     [okButton setAction:oka];
  122.     
  123.     /* Restore the browser's original target/action. */
  124.     [browser setTarget:browsert];
  125.     [browser setAction:browsera];
  126.     [browser setDoubleAction:browserda];
  127.     return ret;
  128. }
  129. /* Handles ok's for the panel.  I need to pretend to be a cancel,
  130.  * for some reason.  Don't ask me - it wasn't working when I didn't
  131.  * do it, so I left it.
  132.  */
  133. - realOk:sender
  134. {
  135.     const char *formValue=[form stringValueAt:0];
  136.     if( [sender isKindOf:[NXBrowser class]]) {
  137.     /* Causes a visible "bounce" for the okButton, along with
  138.      * running this action.
  139.      */
  140.     return [okButton performClick:sender];
  141.     }
  142.     
  143.         /* If there's data in the form, then don't exit. */
  144.     if( !formValue || !*formValue) {
  145.         /* Mark this as a fake Cancel. */
  146.     notCancel=YES;
  147.     
  148.         /* Use the ok: method to pull out any data from the form. */
  149.     [self ok:sender];
  150.     
  151.         /* Use cancel: to get out of the modal loop. */
  152.     return [self cancel:sender];
  153.     } else {
  154.         /* Both of these methods may draw, so flush all at once. */
  155.     [self disableFlushWindow];
  156.     
  157.         /* Aquire the data from the form. */
  158.     [self ok:sender];
  159.     
  160.         /* Make certain that the lastColumn's selection is visible.
  161.          * Consider typing "..".  Without this code, it could
  162.          * ".." right off the left hand side of the browser, and
  163.          * there would be no visible selection and the right hand
  164.          * column would be blank.
  165.          */
  166.     if( [browser numVisibleColumns]>1) {
  167.         [browser scrollColumnToVisible:[browser lastColumn]-1];
  168.     }
  169.     
  170.     [self reenableFlushWindow];
  171.     [self flushWindowIfNeeded];
  172.     return self;
  173.     }
  174. }
  175. @end
  176.