CPCollectionView offset into CPScrollView

50 views
Skip to first unread message

Simon

unread,
Aug 31, 2016, 12:25:09 PM8/31/16
to Cappuccino & Objective-J
Hi all,

First off, I *think* I'm on the latest master. I used the Frameworks/ folder from a 'jake build' output as the one my web server is serving out. I'd be interested to know if there was a foolproof way to know if I was on top-of-tree though...

That said, I'm having some issues with a CPCollectionView being offset into its enclosing CPScrollview. Code looks like:

/*************************************************************************\
|* Create a collection view for the parts
\*************************************************************************/
var H = 40;
frm = CGRectMake(10, y, b.size.width-40, H*6);
var cv = [[CPCollectionView alloc] initWithFrame:frm];
CPLog(@"Items: %@", _items);
[cv setMaxNumberOfColumns:1];
[cv setContent:_items];
[cv setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
[cv setMinItemSize:CGSizeMake(frm.size.width, H)];
[cv setMaxItemSize:CGSizeMake(frm.size.width, H)];

var proto = [CPCollectionViewItem new];
var cvView = [[IParserSubview alloc] initWithFrame:CGRectMakeZero()];
[proto setView:cvView];
[cv setItemPrototype:proto];
frm.size.width += 20; // Vertical scrollbar
frm.size.height += 5*[cv verticalMargin]; // separators
var sv = [[CPScrollView alloc] initWithFrame:frm];
[sv setDocumentView:cv];
[sv setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable];
 [sv setAutohidesScrollers:YES];
[self addSubview:sv];


... which is supposed to lay out a scrollview with 6 elements shown in a collection view at a time, scrollbar on the right. It "pretty much" works, but for some reason the  first row is offset down by ~2 rows-worth of pixels, and the last two elements of the '_items' array are not shown when the scrollbar is at its maximum value.

The data in _items looks like:

2016-08-31 09:05:58.011 Cappuccino [info]: Items: [IParserData:Manufacturer],[IParserData:Manufacturer Part Number],[IParserData:Description],[IParserData:Lead Free Status / RoHS Status],[IParserData:Moisture Sensitivity Level (MSL)],[IParserData:Category],[IParserData:Family],[IParserData:Series],[IParserData:Packaging],[IParserData:Part Status],[IParserData:Resistance (Ohms)],[IParserData:Tolerance],[IParserData:Power (Watts)],[IParserData:Composition],[IParserData:Features],[IParserData:Temperature Coefficient],[IParserData:Operating Temperature],[IParserData:Package / Case],[IParserData:Supplier Device Package],[IParserData:Size / Dimension],[IParserData:Height],[IParserData:Number of Terminations]


 ... with each entry in _items being an IParserData object which has various properties, but I'm only showing the 'name' one above. When launched, the top of the view looks like:


... which (if it hasn't been reduced too far) you can see shows the first item but it's offset down. When the scrollbar is fully maxed out, it looks like:



... and I don't know if it's readable, but that last visible element is 'Size/Dimension', which is the thrird-to-last element in the _items array dumped out above. I doubt it's a coincidence that the extra space at the top of the scrollview is pretty much what would be needed for the display of the rest of the items at the bottom...

The item-view used for each element of the CPCollectionView itself is very basic:

@import <AppKit/AppKit.j>

@import "IParserData.j"

@implementation IParserSubview : CPView
{
CPTextField _fieldName;
CPColor _bg;
}

/*****************************************************************************\
|* Create the subviews 
\*****************************************************************************/
- (void) layout:(IParserData)d
{
var b = [self bounds];
var y = 2;

var frm = CGRectMake(2, y, 250, 18);
_fieldName = [[CPTextField alloc] initWithFrame:frm];
[_fieldName setAlignment:CPRightTextAlignment];
[_fieldName setEditable:NO];
[_fieldName setTextColor:[CPColor whiteColor]];
[_fieldName setFont:[CPFont boldSystemFontOfSize:FONT_LARGE]];
[self addSubview:_fieldName];
}
/*****************************************************************************\
|* Allow interaction with the collection view 
\*****************************************************************************/
- (void)setRepresentedObject:(IParserData)data
{
if (_fieldName == nil)
[self layout:data];
if (data != nil)
{
[_fieldName setStringValue:[data name]];
if ([data toggled])
_bg = [CPColor colorWithWhite:1.0 alpha:0.2];
else
_bg = [CPColor colorWithWhite:1.0 alpha:0.1];
}
}

/*****************************************************************************\
|* Allow selection 
\*****************************************************************************/
- (void)setSelected:(BOOL)isSelected
{
[self setBackgroundColor:isSelected ? [CPColor grayColor] : nil];
}

/*****************************************************************************\
|* Overlay the background with an alternating alpha mask 
\*****************************************************************************/
- (void) drawRect:(CGRect)dirty
{
if (_bg != nil)
{
var ctx = [[CPGraphicsContext currentContext] graphicsPort];
CGContextSetFillColor(ctx, _bg);
CGContextFillRect(ctx, [self bounds]);
}
}
@end



... so I'm presumably doing something stupid with the CPCollectionView setup or the CPScrollView setup. Anyone any ideas ?

Cheers
   Simon

Simon

unread,
Aug 31, 2016, 9:50:31 PM8/31/16
to Cappuccino & Objective-J
So, in the grand tradition of replying to oneself, I found the bug.

I was too caught up in the complexity of the new (to me) CPCollectionView that I'd overlooked the (to quote my dad) "bleedin' obvious" bit where the frame I'm specifying for the Collection view within the scroll view had an X,Y offset. It was a hangover from when I was just getting the data model to work, before I had the scrollview at all.

Once I'd set the first definition above to 

        frm     = CGRectMake(0,0, b.size.width-40, H*6);

... everything worked just fine. PEBCAK strikes again!

Martin Carlberg

unread,
Sep 1, 2016, 12:18:06 AM9/1/16
to objec...@googlegroups.com
Hi Simon,

Nice that you found the problem yourself :-).


Happy coding!

- Martin

--
You received this message because you are subscribed to the Google Groups "Cappuccino & Objective-J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to objectivej+...@googlegroups.com.
To post to this group, send email to objec...@googlegroups.com.
Visit this group at https://groups.google.com/group/objectivej.
For more options, visit https://groups.google.com/d/optout.

Simon

unread,
Sep 1, 2016, 11:25:33 AM9/1/16
to Cappuccino & Objective-J
Yep :)

One teensy bug that caught my eye (just because I was looking at the heights so closely) is that the height of the collection view is calculated as:

    height = MAX(height, numberOfRows * (_minItemSize.height + _verticalMargin));

and the layout is done by:

    [displayItems enumerateObjectsUsingBlock:function(item, idx, stop)
    {
        var view = [item view];

        if (idx >= displayCount)
        {
            [view setFrameOrigin:CGPointMake(-anItemSize.width, -anItemSize.height)];
            return;
        }

        if (idx % numberOfColumns == 0)
        {
            x = _horizontalMargin;
            y += _verticalMargin + anItemSize.height;
        }

        [view setFrameOrigin:CGPointMake(x, y)];
        [view setFrameSize:anItemSize];

        x += anItemSize.width + _horizontalMargin;
    }];


... which means there's always an offset of _verticalMargin before the first item in the scrollbar. I was calculating my required height as (height of row * num rows) + (height of margin * num rows - 1) and it was always slightly off (by 5 pixels, since that's the default separation).

The 'idx % numberOfColumns' part probably needs a check for (idx != 0) for the addition of _verticalMargin and the overall height then needs to take into account the lack of an initial separator offset.

Cheers
   Simon

Cacaodev cacaodev

unread,
Sep 17, 2016, 11:17:50 AM9/17/16
to Cappuccino & Objective-J
The 'idx % numberOfColumns' part probably needs a check for (idx != 0) for the addition of _verticalMargin and the overall height then needs to take into account the lack of an initial separator offset.

Can you open an issue for that ? 

Simon

unread,
Sep 19, 2016, 12:16:32 AM9/19/16
to Cappuccino & Objective-J


On Saturday, September 17, 2016 at 8:17:50 AM UTC-7, Cacaodev cacaodev wrote:
The 'idx % numberOfColumns' part probably needs a check for (idx != 0) for the addition of _verticalMargin and the overall height then needs to take into account the lack of an initial separator offset.

Can you open an issue for that ? 

Yeah, I should have thought of that. Done, issue #2483.

Cheers
   Simon
 
Reply all
Reply to author
Forward
0 new messages