Re: How to Change a button state when textFields become not empty

Patrick CARDONA <[email protected]> Fri, 27 Feb 2026 16:37:40 +0100
Newsgroups gmane.comp.lib.gnustep.general
Message-ID <a741a95b1a9d08e4c0810711c1a01013@pi500>
Hello Riccardo,
Hello All,

On 2026-02-26 22:06:48 +0100 Riccardo Mottola
<[email protected]> wrote:

> Patrick CARDONA wrote:
>> Hello,
> 
>> I am working on an Internet Shortcuts Manager (aka SaveLink).
> 
>> I associated the same action (statechange:) on my two fields ('name' 
>> and 
>> 'link').
>> If they are not empty, the 'savebutton' should be enabled.
>> But my button state does never change. Initial state is disabled and 
>> it 
>> remains in this state.
> 
> 
> I didn't download your project, just reading the code.
> 
> Are you sure you get statechange called? is it connected?

It was never called.

> Put an NSLog(@"statechange called") and check.

Si I modified  several things:
- I removed the method statechange.
- I set the class 'SaveLink'  as an NSApp delegate.
- I added two new methods: (1) 'observe' and (2) 'textDidChange' (see
below)
- I connected the textFields to the action 'observe:'

> 
> Put an NSLog(@"Enable"); here so you are sure that the condition is 
> matched 
> and the issue is in setEnabled.

- I put all NSLog messages as recommended.

> 
> You can easily write this condition as:
> 
> if([nameLink length] && [urlLink length])
> 
> It checks that both string are valid and longer than zero. Not 
> necessary, but 
> it can also be quicker, since it will bail out on a nil string.

- I used better comparison statements.

> 
> you could also try to trim spaces.

- I added trim spaces on nameLink.

> 
> Riccardo
> 

Testing:
- Opening a link... then save : working as expected.
- NewLink command or reset button, then save :  working as expected.
- Typing in the form just after the App has started: I did not yet
find the way to make it work.

The code improved:

<SaveLink.m>


<SaveLink_main.m>

and the whole project...

<SaveLink.tar.gz>

-- 
Patrick Cardona - Pi500 - GNU/Linux aarch64 (Debian 13.3)
Xorg (1:7.7+24) - libcairo2 (1.18.4-1+rpt1 arm64) - Window Maker
(0.96.0-4)
GWorkspace (1.1.0 - 02 2025) - Theme: AGNOSTEP - Classic - MUA:
GNUMail (1.4.0 - rev.947)
SaveLink.m (text/plain, 5 KB)
/* All rights reserved */

#import "SaveLink.h"

int isDirectoryExists(const char *path)
{
    struct stat stats;

    stat(path, &stats);

    // Check for file existence
    if (S_ISDIR(stats.st_mode))
        return 1;

    return 0;
}

id getFavPath()
{
 // Retrieving UserName of the current User and then his homeDirectory
  NSString *userName = NSUserName();
  NSString *homeDir = NSHomeDirectoryForUser(userName);
  
  // LANG ENV?
  const char *Lang = getenv("LANG");
  NSString *prefLang = [NSString stringWithFormat:@"%s",Lang];
  NSLog(@"Preferred Language: %@", prefLang);
  NSString *shortLG = [prefLang substringToIndex: 2];
  NSLog(@"Prefix Language: %@", shortLG);
  // Favorites Folder Name?
  NSString *favFolder;
  NSArray *items;
  items = [NSArray arrayWithObjects: @"fr", @"en", nil];
  int item = [items indexOfObject: shortLG];
  switch (item) {
    case 0:
       favFolder = @"/Favoris/";
       break;
    case 1:
       favFolder = @"/Favorites/";
       break;
    default:
       favFolder = @"/Favorites/";
   }
   NSString *favPath = [homeDir stringByAppendingString: favFolder];
   return favPath;
}

@implementation SaveLink

- (IBAction) observe:(id)sender
{
  // Register for notifications
  [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textDidChange:)
                                                 name:NSControlTextDidChangeNotification
                                               object:name];
                                               
  [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textDidChange:)
                                                 name:NSControlTextDidChangeNotification
                                               object:link];
}

- (IBAction) save: (id)sender
{
  NSLog(@"We enter in SaveLink method...");
  // We retrieve values from textFileds outlets
  // Also We trim spaces in the nameLink:
  NSString *nameLink = [[name stringValue] stringByReplacingOccurrencesOfString:@" " withString:@""];
  NSString *urlLink = [link stringValue];
  
  // Setting filePath
  NSString *ext = @".url";
  NSString *favPath = getFavPath();
  
  // Retrieving UserName of the current User and then his homeDirectory
  NSString *userName = NSUserName();
  NSString *homeDir = NSHomeDirectoryForUser(userName);
  // We check Favorites path
  const char *path = [favPath UTF8String];
  if (isDirectoryExists(path))
  {
  NSString *filePath = [[[homeDir stringByAppendingString: @"/Favoris/"] stringByAppendingString: nameLink] stringByAppendingString: ext];
      
  // Preparing the content to write
  NSString *content = [NSString stringWithFormat: @"[InternetShortcut]\nURL=%@\n", urlLink];
  // Writing to File Name.url
  NSError *error;
  BOOL success;

  success = [content writeToFile:filePath
                         atomically:YES
                           encoding:NSUTF8StringEncoding
                              error:&error];

  if (!success) {
    NSLog(@"Failed to write file: %@", [error localizedDescription]);
    [NSApp terminate: self];                   
   }

 NSLog(@"End of save action");
 }
 else
 {
   NSLog(@"Path of Favorites not found!");
   NSAlert *alert = [[[NSAlert alloc] init] autorelease];
   [alert setMessageText:@"Path of Favorites not found!"];
   [alert setInformativeText:@"You should have a Favorites folder in your Home Directory."];
   [alert runModal];
   [NSApp terminate:nil];
 }
}

- (IBAction) reset: (id)sender
{
  [link setStringValue:@""];
  [name setStringValue:@""];
  [name becomeFirstResponder];
  [self observe: nil];
}

- (IBAction) open:  (id)sender
{
  NSString *favPath = getFavPath();
  int lenPath = [favPath length];
  
  // Filter: we want only .url files to open
  NSArray *fileTypes;
  fileTypes = [NSArray arrayWithObjects: @"url", nil];
  // Open Panel
  NSOpenPanel *openPanel;
  openPanel = [[[NSOpenPanel alloc] init] autorelease];
  [openPanel runModalForTypes: fileTypes];
  NSArray *selection;
  selection = [openPanel filenames];
  NSString *openPath = [selection firstObject];
  
  // Get Name of the Link
  NSString *filePath = [openPath substringFromIndex: lenPath];
  int lenFilePath = [filePath length];
  NSString *nameLink = [filePath substringToIndex: lenFilePath - 4];
  [name setStringValue: nameLink];
  
  // Get Link value
  NSString *content;
  content = [NSString stringWithContentsOfFile: openPath];
  NSString *url =  [content substringFromIndex: 23];
  [link setStringValue: url];
  [savebutton setEnabled:YES];
  [self observe: nil];
}

- (void)textDidChange:(NSNotification *)notification
{
  // We retrieve values from textFileds outlets
  NSLog(@"textDidChange called.");
  NSString *nameLink = [name stringValue];
  NSString *urlLink = [link stringValue];
  if([nameLink length])
  {
    if([[urlLink substringToIndex: 4] isEqualToString: @"http"])
    {
      NSLog(@"Button save enabled");
      [savebutton setEnabled:YES];
    }
  }
  else
  { 
    [savebutton setEnabled:NO];
  }
}

@end
SaveLink_main.m (text/plain, 272 B)
/* 
   Project: SaveLink

   Author: patrick

   Created: 2026-02-24 16:14:34 +0100 by patrick
*/

#import <AppKit/AppKit.h>
#import "SaveLink.h"

int 
main(int argc, const char *argv[])
{
  [NSApp setDelegate: [SaveLink new]];
  return NSApplicationMain (argc, argv);
}
SaveLink.tar.gz (application/x-gzip, 13.7 KB) - not displayed