Centering a view in an NSScrollView

  • I have a view in an NSScrollView, when the contentSize of the
    scrollview is larger than my view I want my view to appear
    centered within the scrollview, even as the scrollview is being
    resized. Right now it is tagged to the bottom left. I know I can
    return YES from the isFlipped method to tag it to the top left,
    but like I said, I want it centered. There does not seem to be a
    good way to do this, any ideas?

    Thanks,
    -dustin
  • On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:

    > I have a view in an NSScrollView, when the contentSize of the
    > scrollview is larger than my view I want my view to appear centered
    > within the scrollview, even as the scrollview is being resized. Right
    > now it is tagged to the bottom left. I know I can return YES from the
    > isFlipped method to tag it to the top left, but like I said, I want it
    > centered. There does not seem to be a good way to do this, any ideas?
    >
    >

      I had to work through something similar (zooming in/out in an
    NSScrollView
    on the visible center). If you want to know how to do that, I can tell
    you for sure.

      For this, off the top of my head, you might be able to keep track of
    the
    contentView's bounds and adjust for any changes in size by moving
    the origin. If you NSLog the contentView's bounds in your drawRect you
    might be able to figure out how to keep things centered.

      Regards,

      Chris Hamlin
  • On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:

    > I have a view in an NSScrollView, when the contentSize of the
    > scrollview is larger than my view I want my view to appear centered
    > within the scrollview, even as the scrollview is being resized. Right
    > now it is tagged to the bottom left. I know I can return YES from the
    > isFlipped method to tag it to the top left, but like I said, I want it
    > centered. There does not seem to be a good way to do this, any ideas?
    >
    >

      I had to work through something similar (zooming in/out in an
    NSScrollView
    on the visible center). If you want to know how to do that, I can tell
    you for sure.

      For this, off the top of my head, you might be able to keep track of
    the
    contentView's bounds and adjust for any changes in size by moving
    the origin. If you NSLog the contentView's bounds in your drawRect you
    might be able to figure out how to keep things centered.

      Regards,

      Chris Hamlin
  • On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:

    > I have a view in an NSScrollView, when the contentSize of the
    > scrollview is larger than my view I want my view to appear centered
    > within the scrollview, even as the scrollview is being resized. Right
    > now it is tagged to the bottom left. I know I can return YES from the
    > isFlipped method to tag it to the top left, but like I said, I want it
    > centered. There does not seem to be a good way to do this, any ideas?
    >

      OK, try this:

      You need to get to the contentView. I think this is the superview of
    your view, but I just made an outlet to the NSScrollview called
    theScrollView. I had an ivar called savedBounds that was
    initialized in awakeFromNib as

            savedBounds = [[theScrollView contentView] bounds];

    Then, in your drawRect (or wherever you actually
    draw), before you draw, check the change in width and
    height of the bounds vs your saved version and subtract
    half of each difference from the current origin.

      The way I think of it is to center the new (larger)
    contentView on the old (smaller one).

      Given the above settings of theScrollView and savedBounds,
    the following basically works for me (not extensively tested, and I'm a
    beginner so who knows the side effects?). If you find any problems
    I'd like to know about them since I like this and may keep it
    in my application now. Thanks! 8)

        float dx, dy;
        NSRect myBounds;

        // find current bounds
        myBounds = [[theScrollView contentView] bounds];
        if (1) NSLog (@"In redrawView: saved bounds is (%f,%f), %f wide, %f
    high)\n",
                      savedBounds.origin.x, savedBounds.origin.y,
                      savedBounds.size.width, savedBounds.size.height);
        if (1) NSLog (@"In redrawView: content bounds is (%f,%f), %f wide,
    %f high)\n",
                      myBounds.origin.x, myBounds.origin.y,
                      myBounds.size.width, myBounds.size.height);

        // find change from last values
        dx = myBounds.size.width - savedBounds.size.width;
        dy = myBounds.size.height - savedBounds.size.height;
        if (1) NSLog (@"In redrawView: bounds change is (%f,%f)\n", dx, dy);

        // move origin to account for size change (probably
        // should only be done for non-zero).
        [[theScrollView contentView]
                setBoundsOrigin:NSMakePoint(myBounds.origin.x - (0.5 * dx),
    myBounds.origin.y - (0.5 * dy))];

        // recheck w/ NSLog
        myBounds = [[theScrollView contentView] bounds];
        if (1) NSLog (@"In redrawView: content bounds NOW (%f,%f), %f wide,
    %f high)\n",
                      myBounds.origin.x, myBounds.origin.y,
                      myBounds.size.width, myBounds.size.height);

        // save new version for next check
        savedBounds = [[theScrollView contentView] bounds];

      Regards,
      Chris Hamlin
  • On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:

    > I have a view in an NSScrollView, when the contentSize of the
    > scrollview is larger than my view I want my view to appear centered
    > within the scrollview, even as the scrollview is being resized. Right
    > now it is tagged to the bottom left. I know I can return YES from the
    > isFlipped method to tag it to the top left, but like I said, I want it
    > centered. There does not seem to be a good way to do this, any ideas?
    >

      OK, try this:

      You need to get to the contentView. I think this is the superview of
    your view, but I just made an outlet to the NSScrollview called
    theScrollView. I had an ivar called savedBounds that was
    initialized in awakeFromNib as

            savedBounds = [[theScrollView contentView] bounds];

    Then, in your drawRect (or wherever you actually
    draw), before you draw, check the change in width and
    height of the bounds vs your saved version and subtract
    half of each difference from the current origin.

      The way I think of it is to center the new (larger)
    contentView on the old (smaller one).

      Given the above settings of theScrollView and savedBounds,
    the following basically works for me (not extensively tested, and I'm a
    beginner so who knows the side effects?). If you find any problems
    I'd like to know about them since I like this and may keep it
    in my application now. Thanks! 8)

        float dx, dy;
        NSRect myBounds;

        // find current bounds
        myBounds = [[theScrollView contentView] bounds];
        if (1) NSLog (@"In redrawView: saved bounds is (%f,%f), %f wide, %f
    high)\n",
                      savedBounds.origin.x, savedBounds.origin.y,
                      savedBounds.size.width, savedBounds.size.height);
        if (1) NSLog (@"In redrawView: content bounds is (%f,%f), %f wide,
    %f high)\n",
                      myBounds.origin.x, myBounds.origin.y,
                      myBounds.size.width, myBounds.size.height);

        // find change from last values
        dx = myBounds.size.width - savedBounds.size.width;
        dy = myBounds.size.height - savedBounds.size.height;
        if (1) NSLog (@"In redrawView: bounds change is (%f,%f)\n", dx, dy);

        // move origin to account for size change (probably
        // should only be done for non-zero).
        [[theScrollView contentView]
                setBoundsOrigin:NSMakePoint(myBounds.origin.x - (0.5 * dx),
    myBounds.origin.y - (0.5 * dy))];

        // recheck w/ NSLog
        myBounds = [[theScrollView contentView] bounds];
        if (1) NSLog (@"In redrawView: content bounds NOW (%f,%f), %f wide,
    %f high)\n",
                      myBounds.origin.x, myBounds.origin.y,
                      myBounds.size.width, myBounds.size.height);

        // save new version for next check
        savedBounds = [[theScrollView contentView] bounds];

      Regards,
      Chris Hamlin
  • On Sunday, January 20, 2002, at 01:01  PM, Christopher B Hamlin wrote:

    >
    > On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:
    >
    >> I have a view in an NSScrollView, when the contentSize of the scrollview
    >> is larger than my view I want my view to appear centered within the
    >> scrollview, even as the scrollview is being resized. Right now it is
    >> tagged to the bottom left. I know I can return YES from the isFlipped
    >> method to tag it to the top left, but like I said, I want it centered.
    >> There does not seem to be a good way to do this, any ideas?
    >>
    >
    > OK, try this:
    >
    > You need to get to the contentView. I think this is the superview of
    > your view, but I just made an outlet to the NSScrollview called
    > theScrollView. I had an ivar called savedBounds that was
    > initialized in awakeFromNib as
    >
    > savedBounds = [[theScrollView contentView] bounds];
    >

    Or just this
    size = [theScrollView contentSize]

    and set the size of the contentView to the size returned above
    frame = [[theScrollView contentView] frame];

    frame.size = size;

    [[theScrollView contentView] setFrame:frame]

    > Then, in your drawRect (or wherever you actually
    > draw), before you draw, check the change in width and
    > height of the bounds vs your saved version and subtract
    > half of each difference from the current origin.
    >
    > The way I think of it is to center the new (larger)
    > contentView on the old (smaller one).
    >
    > Given the above settings of theScrollView and savedBounds,
    > the following basically works for me (not extensively tested, and I'm a
    > beginner so who knows the side effects?). If you find any problems
    > I'd like to know about them since I like this and may keep it
    > in my application now. Thanks! 8)
    >
    >
    >
    >
    > float dx, dy;
    > NSRect myBounds;
    >
    > // find current bounds
    > myBounds = [[theScrollView contentView] bounds];
    > if (1) NSLog (@"In redrawView: saved bounds is (%f,%f), %f wide, %f
    > high)\n",
    > savedBounds.origin.x, savedBounds.origin.y,
    > savedBounds.size.width, savedBounds.size.height);
    > if (1) NSLog (@"In redrawView: content bounds is (%f,%f), %f wide, %f
    > high)\n",
    > myBounds.origin.x, myBounds.origin.y,
    > myBounds.size.width, myBounds.size.height);
    >
    > // find change from last values
    > dx = myBounds.size.width - savedBounds.size.width;
    > dy = myBounds.size.height - savedBounds.size.height;
    > if (1) NSLog (@"In redrawView: bounds change is (%f,%f)\n", dx, dy);
    >
    > // move origin to account for size change (probably
    > // should only be done for non-zero).
    > [[theScrollView contentView]
    > setBoundsOrigin:NSMakePoint(myBounds.origin.x - (0.5 * dx),
    > myBounds.origin.y - (0.5 * dy))];
    >
    > // recheck w/ NSLog
    > myBounds = [[theScrollView contentView] bounds];
    > if (1) NSLog (@"In redrawView: content bounds NOW (%f,%f), %f wide,
    > %f high)\n",
    > myBounds.origin.x, myBounds.origin.y,
    > myBounds.size.width, myBounds.size.height);
    >
    > // save new version for next check
    > savedBounds = [[theScrollView contentView] bounds];
    >
    >
    >
    > Regards,
    > Chris Hamlin
    >
    > _______________________________________________
    > MacOSX-dev mailing list
    > <MacOSX-dev...>
    > http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Sunday, January 20, 2002, at 01:01  PM, Christopher B Hamlin wrote:

    >
    > On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:
    >
    >> I have a view in an NSScrollView, when the contentSize of the scrollview
    >> is larger than my view I want my view to appear centered within the
    >> scrollview, even as the scrollview is being resized. Right now it is
    >> tagged to the bottom left. I know I can return YES from the isFlipped
    >> method to tag it to the top left, but like I said, I want it centered.
    >> There does not seem to be a good way to do this, any ideas?
    >>
    >
    > OK, try this:
    >
    > You need to get to the contentView. I think this is the superview of
    > your view, but I just made an outlet to the NSScrollview called
    > theScrollView. I had an ivar called savedBounds that was
    > initialized in awakeFromNib as
    >
    > savedBounds = [[theScrollView contentView] bounds];
    >

    Or just this
    size = [theScrollView contentSize]

    and set the size of the contentView to the size returned above
    frame = [[theScrollView contentView] frame];

    frame.size = size;

    [[theScrollView contentView] setFrame:frame]

    > Then, in your drawRect (or wherever you actually
    > draw), before you draw, check the change in width and
    > height of the bounds vs your saved version and subtract
    > half of each difference from the current origin.
    >
    > The way I think of it is to center the new (larger)
    > contentView on the old (smaller one).
    >
    > Given the above settings of theScrollView and savedBounds,
    > the following basically works for me (not extensively tested, and I'm a
    > beginner so who knows the side effects?). If you find any problems
    > I'd like to know about them since I like this and may keep it
    > in my application now. Thanks! 8)
    >
    >
    >
    >
    > float dx, dy;
    > NSRect myBounds;
    >
    > // find current bounds
    > myBounds = [[theScrollView contentView] bounds];
    > if (1) NSLog (@"In redrawView: saved bounds is (%f,%f), %f wide, %f
    > high)\n",
    > savedBounds.origin.x, savedBounds.origin.y,
    > savedBounds.size.width, savedBounds.size.height);
    > if (1) NSLog (@"In redrawView: content bounds is (%f,%f), %f wide, %f
    > high)\n",
    > myBounds.origin.x, myBounds.origin.y,
    > myBounds.size.width, myBounds.size.height);
    >
    > // find change from last values
    > dx = myBounds.size.width - savedBounds.size.width;
    > dy = myBounds.size.height - savedBounds.size.height;
    > if (1) NSLog (@"In redrawView: bounds change is (%f,%f)\n", dx, dy);
    >
    > // move origin to account for size change (probably
    > // should only be done for non-zero).
    > [[theScrollView contentView]
    > setBoundsOrigin:NSMakePoint(myBounds.origin.x - (0.5 * dx),
    > myBounds.origin.y - (0.5 * dy))];
    >
    > // recheck w/ NSLog
    > myBounds = [[theScrollView contentView] bounds];
    > if (1) NSLog (@"In redrawView: content bounds NOW (%f,%f), %f wide,
    > %f high)\n",
    > myBounds.origin.x, myBounds.origin.y,
    > myBounds.size.width, myBounds.size.height);
    >
    > // save new version for next check
    > savedBounds = [[theScrollView contentView] bounds];
    >
    >
    >
    > Regards,
    > Chris Hamlin
    >
    > _______________________________________________
    > MacOSX-dev mailing list
    > <MacOSX-dev...>
    > http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Monday, January 21, 2002, at 04:35  PM, Vince DeMarco wrote:

    >
    > On Sunday, January 20, 2002, at 01:01  PM, Christopher B Hamlin wrote:
    >
    >>
    >> On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:
    >>
    >>> I have a view in an NSScrollView, when the contentSize of the
    >>> scrollview is larger than my view I want my view to appear centered
    >>> within the scrollview, even as the scrollview is being resized. Right
    >>> now it is tagged to the bottom left. I know I can return YES from the
    >>> isFlipped method to tag it to the top left, but like I said, I want
    >>> it centered. There does not seem to be a good way to do this, any
    >>> ideas?
    >>>
    >>
    >> OK, try this:
    >>
    >> You need to get to the contentView. I think this is the superview of
    >> your view, but I just made an outlet to the NSScrollview called
    >> theScrollView. I had an ivar called savedBounds that was
    >> initialized in awakeFromNib as
    >>
    >> savedBounds = [[theScrollView contentView] bounds];
    >>
    >
    > Or just this
    > size = [theScrollView contentSize]
    >
    > and set the size of the contentView to the size returned above
    > frame = [[theScrollView contentView] frame];
    >
    > frame.size = size;
    >
    > [[theScrollView contentView] setFrame:frame]
    >

      I tried this, but it doesn't seem to work. I don't think I'm doing
    anything to defeat
    it, but can't get it to work. In logging, I see this at startup:

    >
    > content frame is (1.000000,1.000000), 530.000000 wide, 405.000000 high)
    > content bounds is (-670.000000,0.000000), 530.000000 wide, 405.000000
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 530.000000 wide, 405.000000 high)

    The content frame and bounds are the same size, as are the document frame
    and bounds. Calling [theScrollView contentSize] gives the content
    frame/bounds size.

    If I maximize I get:

    >
    > content frame is (1.000000,1.000000), 1223.000000 wide, 822.000000 high)
    > content bounds is (-670.000000,0.000000), 1223.000000 wide, 822.000000
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 1223.000000 wide, 822.000000 high)

    where the content frame/bounds are both opened up at the same time.
    Seems OK,
    to me? The frame is opened up by the window, and the bounds open too to
    show more
    (rather than zooming in). But the contentSize also changes, so I can't
    see how
    your code will change anything. The documentation doesn't explain if
    contentSize
    is the contentView frame or bounds.

    If I scroll down I get this:

    >
    > content frame is (1.000000,1.000000), 1223.000000 wide, 822.000000 high)
    > content bounds is (-670.000000,78.000000), 1223.000000 wide, 822.000000
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 1223.000000 wide, 822.000000 high)
    >

    The content bounds have just been shifted down. Makes sense.
    Zooming (adjusting the content bounds/origin to zoom in around
    the currently viewed center of the document) then gives this:

    >
    > content frame is (1.000000,1.000000), 1223.000000 wide, 822.000000 high)
    > content bounds is (-547.700012,160.199997), 978.400024 wide, 657.599976
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 1223.000000 wide, 822.000000 high)

    which seems to settle contentSize (it is the content frame size, not
    bounds). But if
    contentSize is the frame size, then how can the above code change
    anything?
    Also, shouldn't I leave the content frame alone, to be handled by the
    superview
    or window?

    If I then resize the window, the content frame and bounds are resized at
    the
    same rate, so my zoom stays. That is soooo cool!

    Is there more documentation or an example
    I'm missing that would help with understanding the interactions in the
    NSScrollView system? The code I have now works OK for center-based
    zooming
    and also I can do what Dustin asked for, but think I'm missing something
    big
    in what you are suggesting. Just when I thought I had it figured
    out . . .

      thanks,

      Chris Hamlin
  • On Monday, January 21, 2002, at 04:35  PM, Vince DeMarco wrote:

    >
    > On Sunday, January 20, 2002, at 01:01  PM, Christopher B Hamlin wrote:
    >
    >>
    >> On Saturday, January 19, 2002, at 10:32  PM, Dustin Mierau wrote:
    >>
    >>> I have a view in an NSScrollView, when the contentSize of the
    >>> scrollview is larger than my view I want my view to appear centered
    >>> within the scrollview, even as the scrollview is being resized. Right
    >>> now it is tagged to the bottom left. I know I can return YES from the
    >>> isFlipped method to tag it to the top left, but like I said, I want
    >>> it centered. There does not seem to be a good way to do this, any
    >>> ideas?
    >>>
    >>
    >> OK, try this:
    >>
    >> You need to get to the contentView. I think this is the superview of
    >> your view, but I just made an outlet to the NSScrollview called
    >> theScrollView. I had an ivar called savedBounds that was
    >> initialized in awakeFromNib as
    >>
    >> savedBounds = [[theScrollView contentView] bounds];
    >>
    >
    > Or just this
    > size = [theScrollView contentSize]
    >
    > and set the size of the contentView to the size returned above
    > frame = [[theScrollView contentView] frame];
    >
    > frame.size = size;
    >
    > [[theScrollView contentView] setFrame:frame]
    >

      I tried this, but it doesn't seem to work. I don't think I'm doing
    anything to defeat
    it, but can't get it to work. In logging, I see this at startup:

    >
    > content frame is (1.000000,1.000000), 530.000000 wide, 405.000000 high)
    > content bounds is (-670.000000,0.000000), 530.000000 wide, 405.000000
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 530.000000 wide, 405.000000 high)

    The content frame and bounds are the same size, as are the document frame
    and bounds. Calling [theScrollView contentSize] gives the content
    frame/bounds size.

    If I maximize I get:

    >
    > content frame is (1.000000,1.000000), 1223.000000 wide, 822.000000 high)
    > content bounds is (-670.000000,0.000000), 1223.000000 wide, 822.000000
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 1223.000000 wide, 822.000000 high)

    where the content frame/bounds are both opened up at the same time.
    Seems OK,
    to me? The frame is opened up by the window, and the bounds open too to
    show more
    (rather than zooming in). But the contentSize also changes, so I can't
    see how
    your code will change anything. The documentation doesn't explain if
    contentSize
    is the contentView frame or bounds.

    If I scroll down I get this:

    >
    > content frame is (1.000000,1.000000), 1223.000000 wide, 822.000000 high)
    > content bounds is (-670.000000,78.000000), 1223.000000 wide, 822.000000
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 1223.000000 wide, 822.000000 high)
    >

    The content bounds have just been shifted down. Makes sense.
    Zooming (adjusting the content bounds/origin to zoom in around
    the currently viewed center of the document) then gives this:

    >
    > content frame is (1.000000,1.000000), 1223.000000 wide, 822.000000 high)
    > content bounds is (-547.700012,160.199997), 978.400024 wide, 657.599976
    > high)
    > document frame is (-670.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > document bounds is (0.000000,0.000000), 1200.000000 wide, 900.000000
    > high)
    > theScrollView contentSize is 1223.000000 wide, 822.000000 high)

    which seems to settle contentSize (it is the content frame size, not
    bounds). But if
    contentSize is the frame size, then how can the above code change
    anything?
    Also, shouldn't I leave the content frame alone, to be handled by the
    superview
    or window?

    If I then resize the window, the content frame and bounds are resized at
    the
    same rate, so my zoom stays. That is soooo cool!

    Is there more documentation or an example
    I'm missing that would help with understanding the interactions in the
    NSScrollView system? The code I have now works OK for center-based
    zooming
    and also I can do what Dustin asked for, but think I'm missing something
    big
    in what you are suggesting. Just when I thought I had it figured
    out . . .

      thanks,

      Chris Hamlin
  • Dustin Mierau  writes:

    > I have a view in an NSScrollView, when the contentSize of the
    > scrollview is larger than my view I want my view to appear
    > centered within the scrollview, even as the scrollview is being
    > resized. Right now it is tagged to the bottom left. I know I can
    > return YES from the isFlipped method to tag it to the top left,
    > but like I said, I want it centered. There does not seem to be a
    > good way to do this, any ideas?

    Well I'm stuck at the same problem.

    I too have a window, with a NSScrollView and a NSView. The view is
    smaler than the scrollView and so I want to reposition the view
    centered in the scrollView. Alltough I can set the new frame for the
    view and acording to the debugger the coordinates are corrct, it will
    be redrawn in the position indicated by its frame.

    On the other hand I have no problem to reposition and change the size
    of a view, which is not connected to a scrollView, but which is
    directly drawn into the window. So now i wonder if there are some
    basic differences concerning a View which is connected to a
    scrollView and one, which is drawn directly into a window.

    greetings henri

    --
previous month january 2002 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today