changeset 2830:cc9258ba53d7

iOS: Remimplement the label and image view in the custom cell. Using the built-in ones is apparently more trouble than it is worth.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 09 Sep 2022 08:42:22 +0000
parents c543f7df7867
children adb0e4ce9347
files ios/dw.m
diffstat 1 files changed, 164 insertions(+), 117 deletions(-) [+]
line wrap: on
line diff
--- a/ios/dw.m	Tue Sep 06 07:07:19 2022 +0000
+++ b/ios/dw.m	Fri Sep 09 08:42:22 2022 +0000
@@ -2337,12 +2337,55 @@
 {
     NSMutableArray *columndata;
     UIStackView *stack;
+    UILabel *label;
+    UIImageView *image;
 }
 -(void)setColumnData:(NSMutableArray *)input;
 -(NSMutableArray *)columnData;
+-(UIImageView *)image;
+-(UILabel *)label;
 @end
 
 @implementation DWTableViewCell
+-(id)init {
+    self = [super init];
+
+    image = [[[UIImageView alloc] init] retain];
+    [image setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [[self contentView] addSubview:image];
+
+    label = [[[UILabel alloc] init] retain];
+    [label setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [[self contentView] addSubview:label];
+
+    stack = [[[UIStackView alloc] init] retain];
+    [stack setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [stack setSpacing:5.0];
+    [[self contentView] addSubview:stack];
+
+    /* Let's use the default margins */
+    UILayoutGuide *g = [[self contentView] layoutMarginsGuide];
+
+    [NSLayoutConstraint activateConstraints:@[
+        /* Constrain label Top/Leading/Trailing to content margins guide */
+        [image.topAnchor constraintEqualToAnchor:g.topAnchor constant:0.0],
+        [image.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:0.0],
+        [image.trailingAnchor constraintEqualToAnchor:label.leadingAnchor constant:-4.0],
+        [label.topAnchor constraintEqualToAnchor:g.topAnchor constant:0.0],
+        [label.leadingAnchor constraintEqualToAnchor:image.trailingAnchor constant:4.0],
+        /* No Height, because we'll use the label's intrinsic size */
+
+        /* Constrain stack view Top to label bottom plus 8-points */
+        [stack.topAnchor constraintEqualToAnchor:label.bottomAnchor constant:0.0],
+        /* Leading/Trailing/Bottom to content margins guide */
+        [stack.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:0.0],
+        [stack.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:0.0],
+        /* No Height, because we'll use the arranged subviews heights */
+    ]];
+    return self;
+}
+-(UILabel *)label { return label; }
+-(UIImageView *)image { return image; }
 -(void)setColumnData:(NSMutableArray *)input
 {
     if(columndata != input)
@@ -2355,124 +2398,108 @@
     /* If we have columndata and are not in default mode */
     if(columndata && _dw_container_mode > DW_CONTAINER_MODE_DEFAULT)
     {
-        /* If we don't have a stack, create one */
-        if(!stack)
-        {
-            NSLayoutConstraint *constraint;
-
-            stack = [[[UIStackView alloc] init] retain];
-            [stack setTranslatesAutoresizingMaskIntoConstraints:NO];
-            [stack setSpacing:5.0];
-            [[self contentView] addSubview:stack];
-
-            /* Leading */
-            constraint = [NSLayoutConstraint constraintWithItem:stack attribute:NSLayoutAttributeLeft
-                                                      relatedBy:NSLayoutRelationEqual toItem:[self contentView]
-                                                      attribute:NSLayoutAttributeLeft multiplier: 1.0 constant:0.0];
-            [[self contentView] addConstraint:constraint];
-
-            /* Top */
-            constraint = [NSLayoutConstraint constraintWithItem:stack attribute:NSLayoutAttributeTop
-                                                      relatedBy:NSLayoutRelationEqual toItem:[self textLabel]
-                                                      attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0];
-            [[self contentView] addConstraint:constraint];
-        }
-        /* Extra and Multi modes create a stack with all the column data */
-        if(_dw_container_mode > DW_CONTAINER_MODE_DEFAULT)
-        {
-            bool extra = _dw_container_mode == DW_CONTAINER_MODE_EXTRA;
-            id subviews = [stack arrangedSubviews];
-            int index = 0;
-
-            /* Extra mode stack is horizontal, multi stack is vertical */
-            [stack setAxis:(extra ? UILayoutConstraintAxisHorizontal : UILayoutConstraintAxisVertical)];
-
-            /* Create the stack using columndata, reusing objects when possible */
-            for(id object in columndata)
-            {
-                if([object isKindOfClass:[NSString class]])
+        bool extra = _dw_container_mode == DW_CONTAINER_MODE_EXTRA;
+        id subviews = [stack arrangedSubviews];
+        int index = 0;
+
+        /* Extra mode stack is horizontal, multi stack is vertical */
+        [stack setAxis:(extra ? UILayoutConstraintAxisHorizontal : UILayoutConstraintAxisVertical)];
+
+        /* Create the stack using columndata, reusing objects when possible */
+        for(id object in columndata)
+        {
+            if([object isKindOfClass:[NSString class]])
+            {
+                id label = nil;
+
+                /* Check if we already have a view, reuse it if possible.. */
+                if(index < [subviews count])
                 {
-                    id label = nil;
-
-                    /* Check if we already have a view, reuse it if possible.. */
-                    if(index < [subviews count])
-                    {
-                        id oldview = [subviews objectAtIndex:index];
-
-                        if([oldview isMemberOfClass:(extra ? [UILabel class] : [UIButton class])])
-                        {
-                            label = oldview;
-                            /* If we are reusing a button, make sure the image is not set */
-                            if(!extra)
-                                [label setImage:nil forState:UIControlStateNormal];
-                        }
-                        else
-                            [stack removeArrangedSubview:oldview];
-                    }
-                    if(!label)
+                    id oldview = [subviews objectAtIndex:index];
+
+                    if([oldview isMemberOfClass:(extra ? [UILabel class] : [UIButton class])])
                     {
-                        label = extra ? [[UILabel alloc] init] : [UIButton buttonWithType:UIButtonTypeCustom];
-
-                        [label setTranslatesAutoresizingMaskIntoConstraints:NO];
-                        if(extra)
-                            [label setTextAlignment:NSTextAlignmentCenter];
-
-                        if(index < [subviews count])
-                            [stack insertArrangedSubview:label atIndex:index];
-                        else /* Remove the view if it won't work */
-                            [stack addArrangedSubview:label];
+                        label = oldview;
+                        /* If we are reusing a button, make sure the image is not set */
+                        if(!extra)
+                            [label setImage:nil forState:UIControlStateNormal];
                     }
-                    /* Set the label or button text/title */
+                    else
+                        [stack removeArrangedSubview:oldview];
+                }
+                if(!label)
+                {
+                    label = extra ? [[UILabel alloc] init] : [UIButton buttonWithType:UIButtonTypeCustom];
+
+                    [label setTranslatesAutoresizingMaskIntoConstraints:NO];
                     if(extra)
-                        [label setText:object];
-                    else
-                        [label setTitle:object forState:UIControlStateNormal];
-                    index++;
+                        [label setTextAlignment:NSTextAlignmentCenter];
+
+                    if(index < [subviews count])
+                        [stack insertArrangedSubview:label atIndex:index];
+                    else /* Remove the view if it won't work */
+                        [stack addArrangedSubview:label];
                 }
-                else if([object isMemberOfClass:[UIImage class]])
+                /* Set the label or button text/title */
+                if(extra)
+                    [label setText:object];
+                else
+                    [label setTitle:object forState:UIControlStateNormal];
+                index++;
+            }
+            else if([object isMemberOfClass:[UIImage class]])
+            {
+                id image = nil;
+
+                /* Check if we already have a view, reuse it if possible.. */
+                if(index < [subviews count])
                 {
-                    id image = nil;
-
-                    /* Check if we already have a view, reuse it if possible.. */
-                    if(index < [subviews count])
+                    id oldview = [subviews objectAtIndex:index];
+
+                    if([oldview isMemberOfClass:(extra ? [UIImageView class] : [UIButton class])])
                     {
-                        id oldview = [subviews objectAtIndex:index];
-
-                        if([oldview isMemberOfClass:(extra ? [UIImageView class] : [UIButton class])])
-                        {
-                            image = oldview;
-                            /* If we are reusing a button, make sure the text is not set */
-                            if(!extra)
-                                [image setTitle:nil forState:UIControlStateNormal];
-                        }
-                        else /* Remove the view if it won't work */
-                            [stack removeArrangedSubview:oldview];
+                        image = oldview;
+                        /* If we are reusing a button, make sure the text is not set */
+                        if(!extra)
+                            [image setTitle:nil forState:UIControlStateNormal];
                     }
-                    if(!image)
-                    {
-                        image = extra ? [[UIImageView alloc] init] : [UIButton buttonWithType:UIButtonTypeCustom];
-
-                        [image setTranslatesAutoresizingMaskIntoConstraints:NO];
-
-                        if(index < [subviews count])
-                            [stack insertArrangedSubview:image atIndex:index];
-                        else
-                            [stack addArrangedSubview:image];
-                    }
-                    /* Set the image view or button image */
-                    if(extra)
-                        [image setImage:object];
+                    else /* Remove the view if it won't work */
+                        [stack removeArrangedSubview:oldview];
+                }
+                if(!image)
+                {
+                    image = extra ? [[UIImageView alloc] init] : [UIButton buttonWithType:UIButtonTypeCustom];
+
+                    [image setTranslatesAutoresizingMaskIntoConstraints:NO];
+
+                    if(index < [subviews count])
+                        [stack insertArrangedSubview:image atIndex:index];
                     else
-                        [image setImage:image forState:UIControlStateNormal];
-
-                    index++;
+                        [stack addArrangedSubview:image];
                 }
+                /* Set the image view or button image */
+                if(extra)
+                    [image setImage:object];
+                else
+                    [image setImage:image forState:UIControlStateNormal];
+
+                index++;
             }
         }
     }
 }
 -(NSMutableArray *)columnData { return columndata; }
--(void)dealloc { [columndata release]; [super dealloc]; [stack removeFromSuperview]; [stack release]; }
+-(void)dealloc
+{
+    [columndata release];
+    [image removeFromSuperview];
+    [image release];
+    [label removeFromSuperview];
+    [label release];
+    [stack removeFromSuperview];
+    [stack release];
+    [super dealloc];
+}
 @end
 
  /* Create a tableview cell for containers using DW_CONTAINER_MODE_* or listboxes */
@@ -2482,9 +2509,9 @@
     [browsercell setAutoresizesSubviews:YES];
 
     if(icon)
-        [[browsercell imageView] setImage:icon];
+        [[browsercell image] setImage:icon];
     if(text)
-        [[browsercell textLabel] setText:text];
+        [[browsercell label] setText:text];
     if(columndata)
         [browsercell setColumnData:columndata];
     return browsercell;
@@ -2549,7 +2576,7 @@
     int index = (int)indexPath.row;
     id celldata = [data objectAtIndex:index];
 
-    /* The data is already a NSTableCellView so just return that */
+    /* The data is already a DWTableViewCell so just return that */
     if([celldata isMemberOfClass:[DWTableViewCell class]])
     {
         DWTableViewCell *result = celldata;
@@ -2558,7 +2585,7 @@
          * and set the text color from the container.
          */
         if(fgcolor)
-            [[result textLabel] setTextColor:fgcolor];
+            [[result label] setTextColor:fgcolor];
 
         /* Return the result */
         return result;
@@ -2582,6 +2609,24 @@
             [cell setBackgroundColor:[UIColor clearColor]];
     }
 }
+-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    int index = (int)indexPath.row;
+    id cell = [data objectAtIndex:index];
+    CGFloat height = 0.0;
+
+    /* The data is already a DWTableViewCell so just return that */
+    if([cell isMemberOfClass:[DWTableViewCell class]])
+    {
+        height = [[cell contentView] systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
+        NSLog(@"Calculated height %f\n", (float)height);
+    }
+    return height > 0.0 ? height : UITableViewAutomaticDimension;
+}
+-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    return _dw_container_mode > DW_CONTAINER_MODE_DEFAULT ? 85.0 : 44.0;
+}
 -(UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point
 {
     DWWindow *window = (DWWindow *)[self window];
@@ -2796,13 +2841,13 @@
                 
                 if([cell imageView])
                 {
-                    thiswidth += [[cell imageView] image].size.width;
-                    thisheight = [[cell imageView] image].size.height;
+                    thiswidth += [[cell image] image].size.width;
+                    thisheight = [[cell image] image].size.height;
                 }
                 if([cell textLabel])
                 {
-                    int textheight = [[cell textLabel] intrinsicContentSize].width;
-                    thiswidth += [[cell textLabel] intrinsicContentSize].width;
+                    int textheight = [[cell label] intrinsicContentSize].width;
+                    thiswidth += [[cell label] intrinsicContentSize].width;
                     if(textheight > thisheight)
                         thisheight = textheight;
                 }
@@ -5616,6 +5661,8 @@
     [cont setDataSource:cont];
     [cont setDelegate:cont];
     [cont setTag:cid];
+    [cont setRowHeight:UITableViewAutomaticDimension];
+    [cont setEstimatedRowHeight:(_dw_container_mode > DW_CONTAINER_MODE_DEFAULT ? 85.0 : 44.0)];
     [cont setRowBgOdd:DW_RGB_TRANSPARENT andEven:DW_RGB_TRANSPARENT];
     return cont;
 }
@@ -5867,7 +5914,7 @@
         else
         {
             DWTableViewCell *cell = [cont getRow:index];
-            NSString *nstr = [[cell textLabel] text];
+            NSString *nstr = [[cell label] text];
 
             strncpy(buffer, [nstr UTF8String], length - 1);
         }
@@ -5906,7 +5953,7 @@
             NSString *nstr = [NSString stringWithUTF8String:buffer];
             DWTableViewCell *cell = [cont getRow:index];
 
-            [[cell textLabel] setText:nstr];
+            [[cell label] setText:nstr];
             [cont reloadData];
             [cont setNeedsDisplay];
         }
@@ -7349,9 +7396,9 @@
         if(column == 0)
         {
             if(icon)
-                [[cell imageView] setImage:icon];
+                [[cell image] setImage:icon];
             else
-                [[cell textLabel] setText:text];
+                [[cell label] setText:text];
         }
         else if(icon || text)
         {
@@ -7454,9 +7501,9 @@
         DWTableViewCell *cell = object;
 
         if(icon)
-            [[cell imageView] setImage:icon];
+            [[cell image] setImage:icon];
         if(text)
-            [[cell textLabel] setText:text];
+            [[cell label] setText:text];
     }
     else /* Otherwise replace it with a new cell */
         [cont editCell:_dw_table_cell_view_new(icon, text, nil) at:(row+lastadd)];