PageRenderTime 170ms CodeModel.GetById 55ms app.highlight 108ms RepoModel.GetById 2ms app.codeStats 0ms

/core/externals/update-engine/externals/gdata-objectivec-client/Examples/MapsSample/MapsSampleWindowController.m

http://macfuse.googlecode.com/
Objective C | 853 lines | 573 code | 221 blank | 59 comment | 80 complexity | 7801a40f9d98559296a8a30147bab742 MD5 | raw file
  1/* Copyright (c) 2009 Google Inc.
  2 *
  3 * Licensed under the Apache License, Version 2.0 (the "License");
  4 * you may not use this file except in compliance with the License.
  5 * You may obtain a copy of the License at
  6 *
  7 *     http://www.apache.org/licenses/LICENSE-2.0
  8 *
  9 * Unless required by applicable law or agreed to in writing, software
 10 * distributed under the License is distributed on an "AS IS" BASIS,
 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12 * See the License for the specific language governing permissions and
 13 * limitations under the License.
 14 */
 15
 16//
 17//  MapSampleWindowController.m
 18//
 19
 20#import "MapsSampleWindowController.h"
 21
 22@interface MapsSampleWindowController (PrivateMethods)
 23- (void)updateUI;
 24
 25- (void)fetchFeedOfMaps;
 26- (void)fetchFeaturesOfSelectedMap;
 27
 28- (void)addAMap;
 29- (void)renameSelectedMap;
 30- (void)deleteSelectedMap;
 31
 32- (void)addFeatureToSelectedMap;
 33- (void)renameSelectedFeature;
 34- (void)deleteSelectedFeature;
 35
 36- (GDataServiceGoogleMaps *)mapService;
 37- (GDataEntryMap *)selectedMap;
 38- (GDataEntryMapFeature *)selectedFeature;
 39
 40
 41- (GDataFeedMap *)mapFeed;
 42- (void)setMapFeed:(GDataFeedMap *)feed;
 43- (NSError *)mapFetchError;
 44- (void)setMapFetchError:(NSError *)error;
 45- (GDataServiceTicket *)mapFeedTicket;
 46- (void)setMapFeedTicket:(GDataServiceTicket *)obj;
 47
 48- (GDataServiceTicket *)mapEditTicket;
 49- (void)setMapEditTicket:(GDataServiceTicket *)obj;
 50
 51- (GDataFeedMapFeature *)featureFeed;
 52- (void)setFeatureFeed:(GDataFeedMapFeature *)feed;
 53- (NSError *)featureFetchError;
 54- (void)setFeatureFetchError:(NSError *)error;
 55- (GDataServiceTicket *)featureFeedTicket;
 56- (void)setFeatureFeedTicket:(GDataServiceTicket *)obj;
 57
 58- (GDataServiceTicket *)featureEditTicket;
 59- (void)setFeatureEditTicket:(GDataServiceTicket *)obj;
 60
 61@end
 62
 63@implementation MapsSampleWindowController
 64
 65+ (MapsSampleWindowController *)sharedWindowController {
 66
 67  static MapsSampleWindowController* gWindowController = nil;
 68
 69  if (!gWindowController) {
 70    gWindowController = [[MapsSampleWindowController alloc] init];
 71  }
 72  return gWindowController;
 73}
 74
 75
 76- (id)init {
 77  return [self initWithWindowNibName:@"MapsSampleWindow"];
 78}
 79
 80- (void)windowDidLoad {
 81}
 82
 83- (void)awakeFromNib {
 84  // Set the result text fields to have a distinctive color and mono-spaced font
 85  [mMapResultTextField setTextColor:[NSColor darkGrayColor]];
 86  [mFeatureResultTextField setTextColor:[NSColor darkGrayColor]];
 87
 88  NSFont *resultTextFont = [NSFont fontWithName:@"Monaco" size:9];
 89  [mMapResultTextField setFont:resultTextFont];
 90  [mFeatureResultTextField setFont:resultTextFont];
 91
 92  [self updateUI];
 93}
 94
 95- (void)dealloc {
 96
 97  [mMapFeed release];
 98  [mMapFeedTicket release];
 99  [mMapFetchError release];
100
101  [mMapEditTicket release];
102
103  [mFeatureFeed release];
104  [mFeatureFeedTicket release];
105  [mFeatureFetchError release];
106
107  [mFeatureEditTicket release];
108
109  [super dealloc];
110}
111
112#pragma mark -
113
114- (void)updateUI {
115
116  // map list display
117  [mMapTable reloadData];
118
119  if (mMapFeedTicket != nil || mMapEditTicket != nil) {
120    [mMapProgressIndicator startAnimation:self];
121  } else {
122    [mMapProgressIndicator stopAnimation:self];
123  }
124
125  // map fetch result or selected item
126  NSString *resultStr = @"";
127  if (mMapFetchError) {
128    resultStr = [mMapFetchError description];
129  } else {
130    GDataEntryMap *map = [self selectedMap];
131    if (map) {
132      resultStr = [map description];
133    }
134  }
135  [mMapResultTextField setString:resultStr];
136
137  // enable map edit buttons
138  BOOL isMapSelected = ([self selectedMap] != nil);
139  BOOL isMapNamePresent = ([[mMapNameField stringValue] length] > 0);
140
141  [mAddMapButton setEnabled:isMapNamePresent];
142  [mRenameMapButton setEnabled:(isMapSelected && isMapNamePresent)];
143  [mDeleteMapButton setEnabled:isMapSelected];
144
145  // features list display
146  [mFeatureTable reloadData];
147
148  if (mFeatureFeedTicket != nil || mFeatureEditTicket != nil) {
149    [mFeatureProgressIndicator startAnimation:self];
150  } else {
151    [mFeatureProgressIndicator stopAnimation:self];
152  }
153
154  // feature fetch result or selected item
155  resultStr = @"";
156  if (mFeatureFetchError) {
157    resultStr = [mFeatureFetchError description];
158  } else {
159    GDataEntryMapFeature *feature = [self selectedFeature];
160    if (feature) {
161      resultStr = [feature description];
162    }
163  }
164  [mFeatureResultTextField setString:resultStr];
165
166  // enable feature edit buttons
167  BOOL isFeatureSelected = ([self selectedFeature] != nil);
168  BOOL isFeatureNamePresent = ([[mFeatureNameField stringValue] length] > 0);
169
170  [mAddFeatureButton setEnabled:isFeatureNamePresent];
171  [mRenameFeatureButton setEnabled:(isFeatureSelected && isFeatureNamePresent)];
172  [mDeleteFeatureButton setEnabled:isFeatureSelected];
173}
174
175#pragma mark IBActions
176
177- (IBAction)getMapsClicked:(id)sender {
178
179  NSCharacterSet *wsSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
180
181  NSString *username = [mUsernameField stringValue];
182  username = [username stringByTrimmingCharactersInSet:wsSet];
183
184  if ([username rangeOfString:@"@"].location == NSNotFound) {
185    // if no domain was supplied, add @gmail.com
186    username = [username stringByAppendingString:@"@gmail.com"];
187  }
188
189  [mUsernameField setStringValue:username];
190
191  [self fetchFeedOfMaps];
192}
193
194- (IBAction)spatialSearchClicked:(id)sender {
195  [self fetchFeaturesOfSelectedMap];
196}
197
198- (IBAction)addMapClicked:(id)sender {
199  [self addAMap];
200}
201
202- (IBAction)renameMapClicked:(id)sender {
203  [self renameSelectedMap];
204}
205
206- (IBAction)deleteMapClicked:(id)sender {
207
208  GDataEntryMap *map = [self selectedMap];
209
210  NSBeginAlertSheet(@"Delete", nil, @"Cancel", nil,
211                    [self window], self,
212                    @selector(deleteMapSheetDidEnd:returnCode:contextInfo:),
213                    nil, nil, @"Delete map \"%@\"?",
214                    [[map title] stringValue]);
215}
216
217- (void)deleteMapSheetDidEnd:(NSWindow *)sheet
218               returnCode:(int)returnCode
219              contextInfo:(void  *)contextInfo {
220
221  if (returnCode == NSOKButton) {
222    [self deleteSelectedMap];
223  }
224}
225
226- (IBAction)addFeatureClicked:(id)sender {
227  [self addFeatureToSelectedMap];
228}
229
230- (IBAction)renameFeatureClicked:(id)sender {
231  [self renameSelectedFeature];
232}
233
234- (IBAction)deleteFeatureClicked:(id)sender {
235  GDataEntryMapFeature *feature = [self selectedFeature];
236
237  NSBeginAlertSheet(@"Delete", nil, @"Cancel", nil,
238                    [self window], self,
239                    @selector(deleteFeatureSheetDidEnd:returnCode:contextInfo:),
240                    nil, nil, @"Delete feature \"%@\"?",
241                    [[feature title] stringValue]);
242}
243
244- (void)deleteFeatureSheetDidEnd:(NSWindow *)sheet
245                  returnCode:(int)returnCode
246                 contextInfo:(void  *)contextInfo {
247
248  if (returnCode == NSOKButton) {
249    [self deleteSelectedFeature];
250  }
251}
252
253- (IBAction)loggingCheckboxClicked:(id)sender {
254  [GTMHTTPFetcher setLoggingEnabled:[sender state]];
255}
256
257#pragma mark -
258
259// get a map service object with the current username/password
260//
261// A "service" object handles networking tasks.  Service objects
262// contain user authentication information as well as networking
263// state information (such as cookies and the "last modified" date for
264// fetched data.)
265
266- (GDataServiceGoogleMaps *)mapService {
267
268  static GDataServiceGoogleMaps* service = nil;
269
270  if (!service) {
271    service = [[GDataServiceGoogleMaps alloc] init];
272
273    [service setShouldCacheResponseData:YES];
274    [service setServiceShouldFollowNextLinks:YES];
275  }
276
277  // username/password may change
278  NSString *username = [mUsernameField stringValue];
279  NSString *password = [mPasswordField stringValue];
280
281  [service setUserCredentialsWithUsername:username
282                                 password:password];
283
284  return service;
285}
286
287// get the map selected in the top list, or nil if none
288- (GDataEntryMap *)selectedMap {
289
290  NSArray *maps = [mMapFeed entries];
291  int rowIndex = [mMapTable selectedRow];
292  if ([maps count] > 0 && rowIndex > -1) {
293
294    GDataEntryMap *map = [maps objectAtIndex:rowIndex];
295    return map;
296  }
297  return nil;
298}
299
300// get the feature selected in the second list, or nil if none
301- (GDataEntryMapFeature *)selectedFeature {
302
303  NSArray *features = [mFeatureFeed entries];
304  int rowIndex = [mFeatureTable selectedRow];
305  if ([features count] > 0 && rowIndex > -1) {
306
307    GDataEntryMapFeature *feature = [features objectAtIndex:rowIndex];
308    return feature;
309  }
310  return nil;
311}
312
313
314#pragma mark Fetch feed of all of the user's maps
315
316// begin retrieving the list of the user's maps
317- (void)fetchFeedOfMaps {
318
319  [self setMapFeed:nil];
320  [self setMapFetchError:nil];
321
322  [self setFeatureFeed:nil];
323  [self setFeatureFeedTicket:nil];
324  [self setFeatureFetchError:nil];
325
326
327  GDataServiceGoogleMaps *service = [self mapService];
328  NSURL *feedURL = [GDataServiceGoogleMaps mapsFeedURLForUserID:kGDataServiceDefaultUser
329                                                     projection:kGDataMapsProjectionFull];
330
331  GDataServiceTicket *ticket;
332  ticket = [service fetchFeedWithURL:feedURL
333                            delegate:self
334                   didFinishSelector:@selector(mapsTicket:finishedWithFeed:error:)];
335  [self setMapFeedTicket:ticket];
336
337  [self updateUI];
338}
339
340// map feed fetch callback
341- (void)mapsTicket:(GDataServiceTicket *)ticket
342  finishedWithFeed:(GDataFeedMap *)feed
343             error:(NSError *)error {
344
345  [self setMapFeed:feed];
346  [self setMapFetchError:error];
347  [self setMapFeedTicket:nil];
348
349  [self updateUI];
350}
351
352#pragma mark Fetch a map's features
353
354// for the map selected in the top list, begin retrieving the lists of
355// features and tables
356- (void)fetchFeaturesOfSelectedMap {
357
358  GDataEntryMap *map = [self selectedMap];
359  if (map) {
360
361    GDataServiceGoogleMaps *service = [self mapService];
362
363    // fetch the feed of features
364    NSURL *featuresFeedURL = [map featuresFeedURL];
365    if (featuresFeedURL) {
366      GDataQueryMaps *query;
367
368      if ([mSpatialSearchCheckbox state] == NSOffState) {
369        // fetch all features of the selected map
370        query = [GDataQueryMaps mapsQueryWithFeedURL:featuresFeedURL];
371      } else {
372        // The "In circle:" checkbox is selected, so do a snippet query with
373        // the user's specified parameters
374
375        // The Maps API does not provide a clean way to get the URL for the
376        // snippets feed (bug 2335402)
377        NSString *featuresStr = [featuresFeedURL absoluteString];
378        NSString *snippetsStr = [featuresStr stringByReplacingOccurrencesOfString:@"/full"
379                                                                       withString:@"/snippet"];
380        NSURL *snippetsURL = [NSURL URLWithString:snippetsStr];
381        query = [GDataQueryMaps mapsQueryWithFeedURL:snippetsURL];
382
383        // put the user's spatial settings into the query
384        double lat = [mLatitudeField doubleValue];
385        double lon = [mLongitudeField doubleValue];
386        double radius = [mRadiusField doubleValue];
387
388        [query setLatitude:lat];
389        [query setLongitude:lon];
390        [query setRadius:radius];
391      }
392
393      [self setFeatureFeed:nil];
394      [self setFeatureFetchError:nil];
395
396      GDataServiceTicket *ticket;
397      ticket = [service fetchFeedWithQuery:query
398                                  delegate:self
399                         didFinishSelector:@selector(featuresTicket:finishedWithFeed:error:)];
400      [self setFeatureFeedTicket:ticket];
401    }
402    [self updateUI];
403  }
404}
405
406// features fetch callback
407- (void)featuresTicket:(GDataServiceTicket *)ticket
408      finishedWithFeed:(GDataFeedMapFeature *)feed
409                 error:(NSError *)error {
410
411  [self setFeatureFeed:feed];
412  [self setFeatureFetchError:error];
413  [self setFeatureFeedTicket:nil];
414
415  [self updateUI];
416}
417
418#pragma mark Add a map
419
420- (void)addAMap {
421
422  NSURL *postURL = [[mMapFeed postLink] URL];
423
424  NSString *title = [mMapNameField stringValue];
425
426  if (postURL != nil && [title length] > 0) {
427    GDataEntryMap *newEntry = [GDataEntryMap mapEntryWithTitle:title];
428
429    NSString *summaryStr = [NSString stringWithFormat:@"Map created %@",
430                            [NSDate date]];
431    [newEntry setSummaryWithString:summaryStr];
432
433    GDataServiceGoogleMaps *service = [self mapService];
434
435    GDataServiceTicket *ticket;
436    ticket = [service fetchEntryByInsertingEntry:newEntry
437                                      forFeedURL:postURL
438                                        delegate:self
439                               didFinishSelector:@selector(addMapTicket:finishedWithEntry:error:)];
440    [self setMapEditTicket:ticket];
441    [self updateUI];
442  }
443}
444
445- (void)addMapTicket:(GDataServiceTicket *)ticket
446   finishedWithEntry:(GDataEntryMap *)entry
447               error:(NSError *)error {
448
449  [self setMapEditTicket:nil];
450
451  if (error == nil) {
452    NSBeginAlertSheet(@"Map added", nil, nil, nil,
453                      [self window], nil, nil,
454                      nil, nil, @"Added map \"%@\"", [[entry title] stringValue]);
455
456    [self fetchFeedOfMaps];
457  } else {
458    NSBeginAlertSheet(@"Add Map Error", nil, nil, nil,
459                      [self window], nil, nil,
460                      nil, nil, @"%@", error);
461
462    [self updateUI];
463  }
464}
465
466#pragma mark Rename a map
467
468- (void)renameSelectedMap {
469
470  GDataEntryMap *selectedMap = [self selectedMap];
471
472  NSString *newName = [mMapNameField stringValue];
473
474  NSURL *editURL = [[selectedMap editLink] URL];
475
476  if (editURL != nil && [newName length] > 0) {
477
478    GDataServiceGoogleMaps *service = [self mapService];
479
480    [selectedMap setTitleWithString:newName];
481
482    GDataServiceTicket *ticket;
483    ticket = [service fetchEntryByUpdatingEntry:selectedMap
484                                       delegate:self
485                              didFinishSelector:@selector(renameMapTicket:finishedWithEntry:error:)];
486    [self setMapEditTicket:ticket];
487    [self updateUI];
488  }
489}
490
491// rename map callback
492- (void)renameMapTicket:(GDataServiceTicket *)ticket
493      finishedWithEntry:(GDataEntryMap *)entry
494                  error:(NSError *)error {
495
496  [self setMapEditTicket:nil];
497
498  if (error == nil) {
499    NSBeginAlertSheet(@"Map renamed", nil, nil, nil,
500                      [self window], nil, nil,
501                      nil, nil, @"Renamed map to \"%@\"",
502                      [[entry title] stringValue]);
503
504    [self fetchFeedOfMaps];
505  } else {
506    NSBeginAlertSheet(@"Rename Map Error", nil, nil, nil,
507                      [self window], nil, nil,
508                      nil, nil, @"%@", error);
509
510    [self updateUI];
511  }
512}
513
514#pragma mark Delete the map
515
516- (void)deleteSelectedMap {
517
518  GDataEntryMap *selectedMap = [self selectedMap];
519  if (selectedMap) {
520
521    GDataServiceGoogleMaps *service = [self mapService];
522    GDataServiceTicket *ticket;
523
524    ticket = [service deleteEntry:selectedMap
525                         delegate:self
526                didFinishSelector:@selector(deleteMapTicket:finishedWithNil:error:)];
527    [self setMapEditTicket:ticket];
528
529    // save the name in the ticket
530    [ticket setProperty:[[selectedMap title] stringValue]
531                 forKey:@"mapName"];
532
533    [self updateUI];
534  }
535}
536
537- (void)deleteMapTicket:(GDataServiceTicket *)ticket
538        finishedWithNil:(GDataObject *)nilObj
539                  error:(NSError *)error {
540
541  [self setMapEditTicket:nil];
542
543  if (error == nil) {
544    NSString *name = [ticket propertyForKey:@"mapName"];
545
546    NSBeginAlertSheet(@"Map deleted", nil, nil, nil,
547                      [self window], nil, nil,
548                      nil, nil, @"Deleted map \"%@\"", name);
549
550    [self fetchFeedOfMaps];
551  } else {
552    NSBeginAlertSheet(@"Delete Map Error", nil, nil, nil,
553                      [self window], nil, nil,
554                      nil, nil, @"%@", error);
555
556    [self updateUI];
557  }
558}
559
560#pragma mark Add a feature
561
562- (void)addFeatureToSelectedMap {
563
564  NSURL *postURL = [[mFeatureFeed postLink] URL];
565
566  NSString *title = [mFeatureNameField stringValue];
567
568  if (postURL != nil && [title length] > 0) {
569
570    GDataEntryMapFeature *newEntry = [GDataEntryMapFeature featureEntryWithTitle:title];
571
572    NSString *summaryStr = [NSString stringWithFormat:@"Feature created %@",
573                            [NSDate date]];
574    [newEntry setSummaryWithString:summaryStr];
575
576    NSString *kmlStr = @"<Placemark xmlns='http://earth.google.com/kml/2.2'>"
577    "<name>Faulkner's Birthplace</name><Point><coordinates>"
578    "-89.520753,34.360902,0.0</coordinates></Point></Placemark>";
579
580    NSError *error = nil;
581    NSXMLElement *kmlElem;
582    kmlElem = [[[NSXMLElement alloc] initWithXMLString:kmlStr
583                                                 error:&error] autorelease];
584    if (kmlElem) {
585      [newEntry addKMLValue:kmlElem];
586    } else {
587      NSLog(@"cannot make kml element, %@", error);
588    }
589
590    GDataServiceGoogleMaps *service = [self mapService];
591
592    GDataServiceTicket *ticket;
593    ticket = [service fetchEntryByInsertingEntry:newEntry
594                                      forFeedURL:postURL
595                                        delegate:self
596                               didFinishSelector:@selector(addFeatureTicket:finishedWithEntry:error:)];
597    [self setFeatureEditTicket:ticket];
598    [self updateUI];
599  }
600}
601
602- (void)addFeatureTicket:(GDataServiceTicket *)ticket
603       finishedWithEntry:(GDataEntryMap *)entry
604                   error:(NSError *)error {
605
606  [self setFeatureEditTicket:nil];
607
608  if (error == nil) {
609    NSBeginAlertSheet(@"Feature added", nil, nil, nil,
610                      [self window], nil, nil,
611                      nil, nil, @"Added feature \"%@\"",
612                      [[entry title] stringValue]);
613
614    [self fetchFeaturesOfSelectedMap];
615  } else {
616    NSBeginAlertSheet(@"Add Feature Error", nil, nil, nil,
617                      [self window], nil, nil,
618                      nil, nil, @"%@", error);
619
620    [self updateUI];
621  }
622}
623
624#pragma mark Rename a feature
625
626- (void)renameSelectedFeature {
627
628  GDataEntryMapFeature *selectedFeature = [self selectedFeature];
629
630  NSString *newName = [mFeatureNameField stringValue];
631
632  NSURL *editURL = [[selectedFeature editLink] URL];
633
634  if (editURL != nil && [newName length] > 0) {
635
636    GDataServiceGoogleMaps *service = [self mapService];
637
638    // reuse the title object in the feature entry, since it has the proper
639    // namespaces needed for editing features, as those are returned from
640    // the server with a default namespace of kml
641    //
642    // if we called [selectedFeature setTitleWithString:] that would create
643    // a new title object, without the namespacing expected when updating
644    // feature entries
645    [[selectedFeature title] setStringValue:newName];
646
647    GDataServiceTicket *ticket;
648    ticket = [service fetchEntryByUpdatingEntry:selectedFeature
649                                       delegate:self
650                              didFinishSelector:@selector(renameFeatureTicket:finishedWithEntry:error:)];
651    [self setFeatureEditTicket:ticket];
652    [self updateUI];
653  }
654}
655
656- (void)renameFeatureTicket:(GDataServiceTicket *)ticket
657          finishedWithEntry:(GDataEntryMapFeature *)entry
658                      error:(NSError *)error {
659
660  [self setFeatureEditTicket:nil];
661
662  if (error == nil) {
663    NSBeginAlertSheet(@"Feature renamed", nil, nil, nil,
664                      [self window], nil, nil,
665                      nil, nil, @"Renamed feature to \"%@\"",
666                      [[entry title] stringValue]);
667
668    [self fetchFeaturesOfSelectedMap];
669  } else {
670    NSBeginAlertSheet(@"Rename Feature Error", nil, nil, nil,
671                      [self window], nil, nil,
672                      nil, nil, @"%@", error);
673
674    [self updateUI];
675  }
676}
677
678#pragma mark Delete the feature
679
680- (void)deleteSelectedFeature {
681
682  GDataEntryMapFeature *selectedFeature = [self selectedFeature];
683  if (selectedFeature) {
684
685    GDataServiceGoogleMaps *service = [self mapService];
686    GDataServiceTicket *ticket;
687
688    ticket = [service deleteEntry:selectedFeature
689                         delegate:self
690                didFinishSelector:@selector(deleteFeatureTicket:finishedWithNil:error:)];
691    [self setFeatureEditTicket:ticket];
692
693    // save the name in the ticket
694    [ticket setProperty:[[selectedFeature title] stringValue]
695                 forKey:@"featureName"];
696
697    [self updateUI];
698  }
699}
700
701- (void)deleteFeatureTicket:(GDataServiceTicket *)ticket
702            finishedWithNil:(GDataObject *)nilObj
703                      error:(NSError *)error {
704
705  [self setFeatureEditTicket:nil];
706
707  if (error == nil) {
708    NSString *name = [ticket propertyForKey:@"featureName"];
709
710    NSBeginAlertSheet(@"Feature deleted", nil, nil, nil,
711                      [self window], nil, nil,
712                      nil, nil, @"Deleted feature \"%@\"", name);
713
714    [self fetchFeaturesOfSelectedMap];
715  } else {
716    NSBeginAlertSheet(@"Delete Feature Error", nil, nil, nil,
717                      [self window], nil, nil,
718                      nil, nil, @"%@", error);
719
720    [self updateUI];
721  }
722}
723
724#pragma mark Text field delegate methods
725
726- (void)controlTextDidChange:(NSNotification *)note {
727
728  [self updateUI]; // enabled/disable buttons
729}
730
731#pragma mark TableView delegate and data source methods
732
733- (void)tableViewSelectionDidChange:(NSNotification *)notification {
734
735  id obj = [notification object];
736  if (obj == mMapTable) {
737    // the user clicked on a map, so fetch its features and tables
738    [self fetchFeaturesOfSelectedMap];
739  } else {
740    // just update the results view for the selected item
741    [self updateUI];
742  }
743}
744
745// table view data source methods
746- (GDataFeedBase *)feedForTableView:(NSTableView *)tableView {
747
748  if (tableView == mMapTable)     return mMapFeed;
749  if (tableView == mFeatureTable) return mFeatureFeed;
750  return nil;
751}
752
753- (int)numberOfRowsInTableView:(NSTableView *)tableView {
754
755  GDataFeedBase *feed = [self feedForTableView:tableView];
756  return [[feed entries] count];
757}
758
759- (id)tableView:(NSTableView *)tableView
760objectValueForTableColumn:(NSTableColumn *)tableColumn
761            row:(int)row {
762
763  GDataFeedBase *feed = [self feedForTableView:tableView];
764  GDataEntryBase *entry = [feed entryAtIndex:row];
765  NSString *title = [[entry title] stringValue];
766
767  if ([entry isKindOfClass:[GDataEntryMap class]]) {
768
769    BOOL isAPIVisible = [(GDataEntryMap *)entry isAPIVisible];
770    if (!isAPIVisible) {
771      title = [title stringByAppendingString:@" (not API visible)"];
772    }
773  }
774
775  return title;
776}
777
778#pragma mark Setters and Getters
779
780- (GDataFeedMap *)mapFeed {
781  return mMapFeed;
782}
783
784- (void)setMapFeed:(GDataFeedMap *)feed {
785  [mMapFeed autorelease];
786  mMapFeed = [feed retain];
787}
788
789- (NSError *)mapFetchError {
790  return mMapFetchError;
791}
792
793- (void)setMapFetchError:(NSError *)error {
794  [mMapFetchError release];
795  mMapFetchError = [error retain];
796}
797
798- (GDataServiceTicket *)mapFeedTicket {
799  return mMapFeedTicket;
800}
801
802- (void)setMapFeedTicket:(GDataServiceTicket *)obj {
803  [mMapFeedTicket autorelease];
804  mMapFeedTicket = [obj retain];
805}
806
807- (GDataServiceTicket *)mapEditTicket {
808  return mMapEditTicket;
809}
810
811- (void)setMapEditTicket:(GDataServiceTicket *)obj {
812  [mMapEditTicket autorelease];
813  mMapEditTicket = [obj retain];
814}
815
816
817- (GDataFeedMapFeature *)featureFeed {
818  return mFeatureFeed;
819}
820
821- (void)setFeatureFeed:(GDataFeedMapFeature *)feed {
822  [mFeatureFeed autorelease];
823  mFeatureFeed = [feed retain];
824}
825
826- (NSError *)featureFetchError {
827  return mFeatureFetchError;
828}
829
830- (void)setFeatureFetchError:(NSError *)error {
831  [mFeatureFetchError release];
832  mFeatureFetchError = [error retain];
833}
834
835- (GDataServiceTicket *)featureFeedTicket {
836  return mFeatureFeedTicket;
837}
838
839- (void)setFeatureFeedTicket:(GDataServiceTicket *)obj {
840  [mFeatureFeedTicket autorelease];
841  mFeatureFeedTicket = [obj retain];
842}
843
844- (GDataServiceTicket *)featureEditTicket {
845  return mFeatureEditTicket;
846}
847
848- (void)setFeatureEditTicket:(GDataServiceTicket *)obj {
849  [mFeatureEditTicket autorelease];
850  mFeatureEditTicket = [obj retain];
851}
852
853@end