Sat, 11 Oct 2025 10:23:22 +0200
more sourcelist styling (Cocoa)
--- a/make/xcode/toolkit/toolkit/main.m Fri Oct 10 15:54:01 2025 +0200 +++ b/make/xcode/toolkit/toolkit/main.m Sat Oct 11 10:23:22 2025 +0200 @@ -40,6 +40,7 @@ UiList *list1; UiList *list2; UiList *sidebar_list; + UiList *sidebar_list2; } MyDocument; MyDocument* create_doc(void) { @@ -69,6 +70,12 @@ ui_list_append(doc->sidebar_list, "Item 5"); ui_list_append(doc->sidebar_list, "Item 6"); + doc->sidebar_list2 = ui_list_new(ctx, "sidebar_list2"); + ui_list_append(doc->sidebar_list2, "Item 1"); + ui_list_append(doc->sidebar_list2, "Item 2"); + ui_list_append(doc->sidebar_list2, "Item 3"); + ui_list_append(doc->sidebar_list2, "Item 4"); + return doc; } @@ -114,11 +121,19 @@ MyDocument *doc = create_doc(); ui_attach_document(obj->ctx, doc); - UiSubList sublist = {0}; - sublist.header = "Test"; - sublist.value = doc->sidebar_list; + UiSubList sublist[2]; + sublist[0].header = "iCloud"; + sublist[0].value = doc->sidebar_list; + sublist[0].separator = FALSE; + sublist[0].varname = NULL; + sublist[0].userdata = NULL; + sublist[1].header = "Tags"; + sublist[1].value = doc->sidebar_list2; + sublist[1].separator = FALSE; + sublist[1].varname = NULL; + sublist[1].userdata = NULL; ui_sidebar(obj) { - ui_sourcelist(obj, .fill = TRUE, .sublists = &sublist, .numsublists = 1); + ui_sourcelist(obj, .fill = TRUE, .sublists = sublist, .numsublists = 2); } @@ -144,23 +159,6 @@ ui_grid(obj, .columnspacing = 10, .rowspacing = 10) { ui_table(obj, .fill = UI_ON, .varname = "list1", .model = model, .getvalue = table_getvalue, .onactivate = action_list_activate, .onselection = action_list_selection, .multiselection = TRUE); } - - - ui_vbox(obj, .spacing = 0, .fill = UI_OFF) { - ui_combobox(obj, .varname = "list2"); - - ui_llabel(obj, .label = "Left Label"); - ui_rlabel(obj, .label = "Right Label"); - - ui_textfield(obj, .varname = "textfield1"); - ui_radiobutton(obj, .label = "V Button 1", .varname = "radio1"); - ui_radiobutton(obj, .label = "V Button 2", .varname = "radio1"); - ui_radiobutton(obj, .label = "V Button 3", .varname = "radio1"); - - ui_radiobutton(obj, .label = "V Button 1 R2", .varname = "radio2"); - ui_radiobutton(obj, .label = "V Button 2 R2", .varname = "radio2"); - ui_radiobutton(obj, .label = "V Button 3 R2", .varname = "radio2"); - } */ ui_show(obj);
--- a/ui/cocoa/list.h Fri Oct 10 15:54:01 2025 +0200 +++ b/ui/cocoa/list.h Sat Oct 11 10:23:22 2025 +0200 @@ -107,6 +107,9 @@ @interface UiSourceListRow : NSTableRowView +@property NSTrackingArea *trackingArea; +@property NSView *disclosureButton; +@property BOOL hover; @end
--- a/ui/cocoa/list.m Fri Oct 10 15:54:01 2025 +0200 +++ b/ui/cocoa/list.m Sat Oct 11 10:23:22 2025 +0200 @@ -416,20 +416,12 @@ outline.rowSizeStyle = NSTableViewRowSizeStyleDefault; outline.usesAutomaticRowHeights = YES; outline.indentationPerLevel = 0; - outline.indentationMarkerFollowsCell = NO; - - outline.floatsGroupRows = NO; - outline.indentationPerLevel = 0.0; - outline.indentationMarkerFollowsCell = NO; - outline.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular; - - // Hide the disclosure triangle - //outline.disclosureButtonImage = nil; outline.style = NSTableViewStyleSourceList; - + outline.selectionHighlightStyle = NSTableViewSelectionHighlightStyleSourceList; + // Make background transparent so vibrancy shows through - outline.backgroundColor = [NSColor clearColor]; + //outline.backgroundColor = [NSColor clearColor]; scrollview.drawsBackground = NO; scrollview.documentView = outline; @@ -458,6 +450,8 @@ outline.dataSource = data; outline.delegate = data; + [data update:-1]; + objc_setAssociatedObject(outline, "ui_datasource", data, OBJC_ASSOCIATION_RETAIN); return (__bridge void*)scrollview; @@ -498,6 +492,7 @@ } [_outlineView reloadData]; + [_outlineView expandItem:nil expandChildren:YES]; } // NSOutlineViewDataSource implementation @@ -525,10 +520,12 @@ } - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { + /* UiSourceListItem *i = item; if([[tableColumn identifier] isEqualToString:@"label"]) { return i.label; } + */ return nil; } @@ -557,22 +554,50 @@ cell.imageView = iconView; // Label - NSTextField *textField = [NSTextField labelWithString:@""]; + //NSTextField *textField = [NSTextField labelWithString:@""]; + NSTextField *textField = [[NSTextField alloc] initWithFrame:NSZeroRect]; textField.translatesAutoresizingMaskIntoConstraints = NO; + textField.bezeled = NO; + textField.editable = NO; + textField.drawsBackground = NO; + textField.selectable = NO; + textField.lineBreakMode = NSLineBreakByTruncatingTail; + + [cell addSubview:textField]; cell.textField = textField; - - // Layout constraints - [NSLayoutConstraint activateConstraints:@[ - [iconView.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0], - [iconView.centerYAnchor constraintEqualToAnchor:cell.centerYAnchor], + + if([i isSection]) { + NSFont *font = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]*0.85]; + //NSFont *font = [NSFont preferredFontForTextStyle:NSFontTextStyleCaption1 options:@{}]; + NSDictionary *attrs = @{ + NSFontAttributeName: font, + NSForegroundColorAttributeName: [NSColor tertiaryLabelColor] + }; + textField.attributedStringValue = [[NSAttributedString alloc] initWithString:i.label attributes:attrs]; + + // Layout constraints + [NSLayoutConstraint activateConstraints:@[ + [iconView.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0], + [iconView.bottomAnchor constraintEqualToAnchor:cell.bottomAnchor constant:-1], - [textField.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0], - [textField.centerYAnchor constraintEqualToAnchor:cell.centerYAnchor], - [textField.trailingAnchor constraintEqualToAnchor:cell.trailingAnchor constant:0], - ]]; - - textField.stringValue = i.label; + [textField.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0], + [textField.bottomAnchor constraintEqualToAnchor:cell.bottomAnchor constant:-1], + [textField.trailingAnchor constraintEqualToAnchor:cell.trailingAnchor constant:0], + ]]; + } else { + textField.stringValue = i.label; + + // Layout constraints + [NSLayoutConstraint activateConstraints:@[ + [iconView.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0], + [iconView.centerYAnchor constraintEqualToAnchor:cell.centerYAnchor], + + [textField.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0], + [textField.centerYAnchor constraintEqualToAnchor:cell.centerYAnchor], + [textField.trailingAnchor constraintEqualToAnchor:cell.trailingAnchor constant:0], + ]]; + } return cell; } @@ -590,6 +615,21 @@ return [i isSection] ? NO : YES; } +- (CGFloat) outlineView:(NSOutlineView *) outlineView + heightOfRowByItem:(id) item +{ + UiSourceListItem *i = item; + CGFloat rowHeight = outlineView.rowHeight; + if([i isSection]) { + if(i.index == 0) { + rowHeight -= 12; + } else { + rowHeight += 4; + } + } + return rowHeight; +} + - (void) outlineViewSelectionDidChange:(NSNotification *) notification { UiEvent event; event.obj = _obj; @@ -690,6 +730,21 @@ NSRect frame = subview.frame; frame.origin.x = self.bounds.size.width - frame.size.width - 16.0; subview.frame = frame; + + if(!_hover) { + subview.hidden = YES; + } + + if(subview != _disclosureButton) { + // init disclosure button + _disclosureButton = (NSButton*)subview; + if ([subview isKindOfClass:[NSButton class]]) { + NSButton *button = (NSButton*)subview; + button.contentTintColor = [NSColor tertiaryLabelColor]; + } + } + + } else if ([subview.identifier isEqualToString:@"cell"]) { NSRect frame = subview.frame; frame.origin.x = 16; @@ -698,4 +753,28 @@ } } +- (void)updateTrackingAreas { + [super updateTrackingAreas]; + if(_trackingArea != nil) { + [self removeTrackingArea:_trackingArea]; + } + _trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds + options:NSTrackingMouseEnteredAndExited | + NSTrackingActiveInActiveApp | + NSTrackingInVisibleRect + owner:self + userInfo:nil]; + [self addTrackingArea:_trackingArea]; +} + +- (void)mouseEntered:(NSEvent *)event { + _hover = YES; + _disclosureButton.hidden = NO; +} + +- (void)mouseExited:(NSEvent *)event { + _hover = NO; + _disclosureButton.hidden = YES; +} + @end