X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=OSX%2FXScreenSaverConfigSheet.m;h=b32e47612a15fe7e2ac36867b227044d114c351a;hb=b81f521c5ad7022ac12db18ca8fcdd9fb063831e;hp=12980fa7cf2f6222c15a3dd8394e797ca46dda62;hpb=f8cf5ac7b2f53510f80a0eaf286a25298be17bfe;p=xscreensaver diff --git a/OSX/XScreenSaverConfigSheet.m b/OSX/XScreenSaverConfigSheet.m index 12980fa7..b32e4761 100644 --- a/OSX/XScreenSaverConfigSheet.m +++ b/OSX/XScreenSaverConfigSheet.m @@ -48,6 +48,7 @@ #endif // USE_IPHONE #undef LABEL_ABOVE_SLIDER +#define USE_HTML_LABELS #pragma mark XML Parser @@ -191,6 +192,222 @@ typedef enum { SimpleXMLCommentKind, # endif // !USE_PICKER_VIEW +# pragma mark Implementing labels with clickable links + +#if defined(USE_IPHONE) && defined(USE_HTML_LABELS) + +@interface HTMLLabel : UIView +{ + NSString *html; + UIFont *font; + UIWebView *webView; +} + +@property(nonatomic, retain) NSString *html; +@property(nonatomic, retain) UIWebView *webView; + +- (id) initWithHTML:(NSString *)h font:(UIFont *)f; +- (id) initWithText:(NSString *)t font:(UIFont *)f; +- (void) setHTML:(NSString *)h; +- (void) setText:(NSString *)t; +- (void) sizeToFit; + +@end + +@implementation HTMLLabel + +@synthesize html; +@synthesize webView; + +- (id) initWithHTML:(NSString *)h font:(UIFont *)f +{ + self = [super init]; + if (! self) return 0; + font = [f retain]; + webView = [[UIWebView alloc] init]; + webView.delegate = self; + webView.dataDetectorTypes = UIDataDetectorTypeNone; + self. autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight); + [self addSubview: webView]; + [self setHTML: h]; + return self; +} + +- (id) initWithText:(NSString *)t font:(UIFont *)f +{ + self = [self initWithHTML:@"" font:f]; + if (! self) return 0; + [self setText: t]; + return self; +} + + +- (void) setHTML: (NSString *)h +{ + if (! h) return; + [h retain]; + if (html) [html release]; + html = h; + NSString *h2 = + [NSString stringWithFormat: + @"" + "" + "" +// "" + "" + "" + "" + "%@" + "" + "", + [font fontName], + [font pointSize], + [font lineHeight], + h]; + [webView loadHTMLString:h2 baseURL:[NSURL URLWithString:@""]]; +} + + +static char *anchorize (const char *url); + +- (void) setText: (NSString *)t +{ + t = [t stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; + t = [t stringByReplacingOccurrencesOfString:@"<" withString:@"<"]; + t = [t stringByReplacingOccurrencesOfString:@">" withString:@">"]; + t = [t stringByReplacingOccurrencesOfString:@"\n\n" withString:@"

"]; + t = [t stringByReplacingOccurrencesOfString:@"

" + withString:@"

        "]; + t = [t stringByReplacingOccurrencesOfString:@"\n " + withString:@"
        "]; + + NSString *h = @""; + for (NSString *s in + [t componentsSeparatedByCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]) { + if ([s hasPrefix:@"http://"] || + [s hasPrefix:@"https://"]) { + char *anchor = anchorize ([s cStringUsingEncoding:NSUTF8StringEncoding]); + NSString *a2 = [NSString stringWithCString: anchor + encoding: NSUTF8StringEncoding]; + s = [NSString stringWithFormat: @"%@
", s, a2]; + free (anchor); + } + h = [NSString stringWithFormat: @"%@ %@", h, s]; + } + [self setHTML: h]; +} + + +-(BOOL) webView:(UIWebView *)wv + shouldStartLoadWithRequest:(NSURLRequest *)req + navigationType:(UIWebViewNavigationType)type +{ + // Force clicked links to open in Safari, not in this window. + if (type == UIWebViewNavigationTypeLinkClicked) { + [[UIApplication sharedApplication] openURL:[req URL]]; + return NO; + } + return YES; +} + + +- (void) setFrame: (CGRect)r +{ + [super setFrame: r]; + r.origin.x = 0; + r.origin.y = 0; + [webView setFrame: r]; + [self setHTML: html]; + [webView reload]; +} + + +- (NSString *) stripTags:(NSString *)str +{ + NSString *result = @""; + + str = [str stringByReplacingOccurrencesOfString:@"

" + withString:@"

" + options:NSCaseInsensitiveSearch + range:NSMakeRange(0, [str length])]; + str = [str stringByReplacingOccurrencesOfString:@"
" + withString:@"\n" + options:NSCaseInsensitiveSearch + range:NSMakeRange(0, [str length])]; + + for (NSString *s in [str componentsSeparatedByString: @"<"]) { + NSRange r = [s rangeOfString:@">"]; + if (r.length > 0) + s = [s substringFromIndex: r.location + r.length]; + result = [result stringByAppendingString: s]; + } + return result; +} + + +- (void) sizeToFit +{ + CGRect r = [self frame]; + + /* It would be sensible to just ask the UIWebView how tall the page is, + instead of hoping that NSString and UIWebView measure fonts and do + wrapping in exactly the same way, but I can't make that work. + Maybe because it loads async? + */ +# if 0 + r.size.height = [[webView + stringByEvaluatingJavaScriptFromString: + @"document.body.offsetHeight"] + doubleValue]; +# else + NSString *text = [self stripTags: html]; + CGSize s = r.size; + s.height = 999999; + s = [text sizeWithFont: font + constrainedToSize: s + lineBreakMode:NSLineBreakByWordWrapping]; + + // GAAAH. Add one more line, or the UIWebView is still scrollable! + // The text is sized right, but it lets you scroll it up anyway. + s.height += [font pointSize]; + + r.size.height = s.height; +# endif + + [self setFrame: r]; +} + + +- (void) dealloc +{ + [html release]; + [font release]; + [webView release]; + [super dealloc]; +} + +@end + +#endif // USE_IPHONE && USE_HTML_LABELS + @interface XScreenSaverConfigSheet (Private) @@ -219,6 +436,7 @@ static void layout_group (NSView *group, BOOL horiz_p); # define LEFT_LABEL_WIDTH 70 // width of all left labels # define LINE_SPACING 10 // leading between each line +# define FONT_SIZE 17 // Magic hardcoded UITableView font size. #pragma mark Talking to the resource database @@ -681,6 +899,8 @@ anchorize (const char *url) } +#if !defined(USE_IPHONE) || !defined(USE_HTML_LABELS) + /* Converts any http: URLs in the given text field to clickable links. */ static void @@ -765,6 +985,9 @@ hreffify (NSText *nstext) # endif } +#endif /* !USE_IPHONE || !USE_HTML_LABELS */ + + #pragma mark Creating controls from XML @@ -812,6 +1035,26 @@ hreffify (NSText *nstext) if ([val length] == 0) [dict removeObjectForKey:key]; } + +# ifdef USE_IPHONE + // Kludge for starwars.xml: + // If there is a "_low-label" and no "_label", but "_low-label" contains + // spaces, divide them. + NSString *lab = [dict objectForKey:@"_label"]; + NSString *low = [dict objectForKey:@"_low-label"]; + if (low && !lab) { + NSArray *split = + [[[low stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]] + componentsSeparatedByString: @" "] + filteredArrayUsingPredicate: + [NSPredicate predicateWithFormat:@"length > 0"]]; + if (split && [split count] == 2) { + [dict setValue:[split objectAtIndex:0] forKey:@"_label"]; + [dict setValue:[split objectAtIndex:1] forKey:@"_low-label"]; + } + } +# endif // USE_IPHONE } @@ -856,7 +1099,8 @@ hreffify (NSText *nstext) [NSCharacterSet whitespaceAndNewlineCharacterSet]]]; [lab setBackgroundColor:[UIColor clearColor]]; [lab setNumberOfLines:0]; // unlimited - [lab setLineBreakMode:UILineBreakModeWordWrap]; + // [lab setLineBreakMode:UILineBreakModeWordWrap]; + [lab setLineBreakMode:NSLineBreakByTruncatingHead]; [lab setAutoresizingMask: (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; # endif // USE_IPHONE @@ -1059,7 +1303,7 @@ hreffify (NSText *nstext) [lab setFrame:rect]; [self placeChild:lab on:parent]; # else // USE_IPHONE - [lab setTextAlignment: UITextAlignmentRight]; + [lab setTextAlignment: NSTextAlignmentRight]; [self placeChild:lab on:parent right:(label ? YES : NO)]; # endif // USE_IPHONE @@ -1429,10 +1673,8 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj) for (NSArray *item in items) { RadioButton *b = [[RadioButton alloc] initWithIndex:i items:items]; - [b setFont:[NSFont boldSystemFontOfSize: - // #### Fucking hardcoded UITableView font size BS! - 17 // [NSFont systemFontSize] - ]]; + [b setLineBreakMode:NSLineBreakByTruncatingHead]; + [b setFont:[NSFont boldSystemFontOfSize: FONT_SIZE]]; [self placeChild:b on:parent]; i++; } @@ -1479,11 +1721,25 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj) hreffify (lab); boldify (lab); [lab sizeToFit]; + # else // USE_IPHONE + +# ifndef USE_HTML_LABELS + UILabel *lab = [self makeLabel:text]; [lab setFont:[NSFont systemFontOfSize: [NSFont systemFontSize]]]; hreffify (lab); + +# else // USE_HTML_LABELS + HTMLLabel *lab = [[HTMLLabel alloc] + initWithText:text + font:[NSFont systemFontOfSize: [NSFont systemFontSize]]]; + [lab setFrame:rect]; + [lab sizeToFit]; +# endif // USE_HTML_LABELS + [self placeSeparator]; + # endif // USE_IPHONE [self placeChild:lab on:parent]; @@ -1536,11 +1792,10 @@ set_menu_item_object (NSMenuItem *item, NSObject *obj) txt.adjustsFontSizeToFitWidth = YES; txt.textColor = [UIColor blackColor]; - // #### Fucking hardcoded UITableView font size BS! - txt.font = [UIFont systemFontOfSize: 17]; + txt.font = [UIFont systemFontOfSize: FONT_SIZE]; txt.placeholder = @""; txt.borderStyle = UITextBorderStyleRoundedRect; - txt.textAlignment = UITextAlignmentRight; + txt.textAlignment = NSTextAlignmentRight; txt.keyboardType = UIKeyboardTypeDefault; // Full kbd txt.autocorrectionType = UITextAutocorrectionTypeNo; txt.autocapitalizationType = UITextAutocapitalizationTypeNone; @@ -2011,7 +2266,6 @@ find_text_field_of_button (NSButton *button) - (void) makeImageLoaderControlBox:(NSXMLNode *)node on:(NSView *)parent { -# ifndef USE_IPHONE /* [x] Grab desktop images [ ] Choose random image: @@ -2026,11 +2280,19 @@ find_text_field_of_button (NSButton *button) NSXMLElement *node2; +# ifndef USE_IPHONE +# define SCREENS "Grab desktop images" +# define PHOTOS "Choose random images" +# else +# define SCREENS "Grab screenshots" +# define PHOTOS "Use photo library" +# endif + node2 = [[NSXMLElement alloc] initWithName:@"boolean"]; [node2 setAttributesAsDictionary: [NSDictionary dictionaryWithObjectsAndKeys: @"grabDesktopImages", @"id", - @"Grab desktop images", @"_label", + @ SCREENS, @"_label", @"-no-grab-desktop", @"arg-unset", nil]]; [self makeCheckbox:node2 on:parent]; @@ -2039,7 +2301,7 @@ find_text_field_of_button (NSButton *button) [node2 setAttributesAsDictionary: [NSDictionary dictionaryWithObjectsAndKeys: @"chooseRandomImages", @"id", - @"Choose random images", @"_label", + @ PHOTOS, @"_label", @"-choose-random-images", @"arg-set", nil]]; [self makeCheckbox:node2 on:parent]; @@ -2054,6 +2316,10 @@ find_text_field_of_button (NSButton *button) [self makeFileSelector:node2 on:parent dirsOnly:YES withLabel:YES editable:YES]; +# undef SCREENS +# undef PHOTOS + +# ifndef USE_IPHONE // Add a second, explanatory label below the file/URL selector. LABEL *lab2 = 0; @@ -2066,7 +2332,7 @@ find_text_field_of_button (NSButton *button) r2.origin.y += 14; [lab2 setFrameOrigin:r2.origin]; [lab2 release]; -# endif // !USE_IPHONE +# endif // USE_IPHONE } @@ -2599,6 +2865,8 @@ wrap_with_buttons (NSWindow *window, NSView *panel) } saver_name = [self parseXScreenSaverTag: node]; + saver_name = [saver_name stringByReplacingOccurrencesOfString:@" " + withString:@""]; [saver_name retain]; # ifndef USE_IPHONE @@ -2698,7 +2966,7 @@ wrap_with_buttons (NSWindow *window, NSView *panel) - (CGFloat)pickerView:(UIPickerView *)pv rowHeightForComponent:(NSInteger)column { - return [NSFont systemFontSize] * 1.5; // #### WHAT + return FONT_SIZE; } - (CGFloat)pickerView:(UIPickerView *)pv @@ -2753,6 +3021,10 @@ wrap_with_buttons (NSWindow *window, NSView *panel) style: UIBarButtonItemStyleBordered target:self action:@selector(resetAction:)]]; + NSString *s = saver_name; + if ([self view].frame.size.width > 320) + s = [s stringByAppendingString: @" Settings"]; + [self navigationItem].title = s; } @@ -2778,8 +3050,8 @@ wrap_with_buttons (NSWindow *window, NSView *panel) titleForHeaderInSection:(NSInteger)section { // Titles above each vertically-stacked white box. - if (section == 0) - return [saver_name stringByAppendingString:@" Settings"]; +// if (section == 0) +// return [saver_name stringByAppendingString:@" Settings"]; return nil; } @@ -2814,7 +3086,20 @@ wrap_with_buttons (NSWindow *window, NSView *panel) [t sizeToFit]; r = t.frame; h = r.size.height + LINE_SPACING * 3; +# ifdef USE_HTML_LABELS + } else if ([ctl isKindOfClass:[HTMLLabel class]]) { + + HTMLLabel *t = (HTMLLabel *) ctl; + CGRect r = t.frame; + r.size.width = [tv frame].size.width; + r.size.width -= LEFT_MARGIN * 2; + [t setFrame:r]; + [t sizeToFit]; + r = t.frame; + h = r.size.height + LINE_SPACING * 3; + +# endif // USE_HTML_LABELS } else { CGFloat h2 = [ctl frame].size.height; h2 += LINE_SPACING * 2; @@ -2955,9 +3240,8 @@ wrap_with_buttons (NSWindow *window, NSView *panel) case 2: { // With 2 elements, the first of the pair must be a label. - ctl = [set objectAtIndex: 0]; - NSAssert ([ctl isKindOfClass:[UILabel class]], @"unhandled type"); - cell.textLabel.text = [(UILabel *) ctl text]; + UILabel *label = (UILabel *) [set objectAtIndex: 0]; + NSAssert ([label isKindOfClass:[UILabel class]], @"unhandled type"); ctl = [set objectAtIndex: 1]; r = [ctl frame]; @@ -2974,6 +3258,24 @@ wrap_with_buttons (NSWindow *window, NSView *panel) } r.origin.y = (p.size.height - r.size.height) / 2; [ctl setFrame:r]; + + // Make a box. + NSView *box = [[UIView alloc] initWithFrame:p]; + [box addSubview: ctl]; + + // cell.textLabel.text = [(UILabel *) ctl text]; + r = [label frame]; + r.origin.x = LEFT_MARGIN; + r.origin.y = 0; + r.size.width = [ctl frame].origin.x - r.origin.x; + r.size.height = p.size.height; + [label setFrame:r]; + [label setFont:[NSFont boldSystemFontOfSize: FONT_SIZE]]; + label.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + box. autoresizingMask = UIViewAutoresizingFlexibleWidth; + [box addSubview: label]; + + ctl = box; } break; case 3: @@ -3008,7 +3310,6 @@ wrap_with_buttons (NSWindow *window, NSView *panel) // Top label goes above, flush center/top. if (top) { - // [top setFont:[[cell textLabel] font]]; // 0 point? r.size = [[top text] sizeWithFont:[top font] constrainedToSize: CGSizeMake (p.size.width - LEFT_MARGIN*2, @@ -3049,7 +3350,14 @@ wrap_with_buttons (NSWindow *window, NSView *panel) top.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin| UIViewAutoresizingFlexibleRightMargin); # else - cell.textLabel.text = [top text]; + r = [top frame]; + r.origin.x = LEFT_MARGIN; + r.origin.y = 0; + r.size.width = [mid frame].origin.x - r.origin.x; + r.size.height = p.size.height; + [top setFrame:r]; + top.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + [ctl addSubview: top]; # endif } [ctl addSubview: left]; @@ -3082,6 +3390,14 @@ wrap_with_buttons (NSWindow *window, NSView *panel) # endif // USE_PICKER_VIEW } + if ([ctl isKindOfClass:[UILabel class]]) { + // Make label full height to allow text to line-wrap if necessary. + r = [ctl frame]; + r.origin.y = p.origin.y; + r.size.height = p.size.height; + [ctl setFrame:r]; + } + [cell.contentView addSubview: ctl]; return cell;