Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 调整窗口大小时,使缩放视图的内容居中且可见_Objective C_Cocoa_Nsview_Nstextview - Fatal编程技术网

Objective c 调整窗口大小时,使缩放视图的内容居中且可见

Objective c 调整窗口大小时,使缩放视图的内容居中且可见,objective-c,cocoa,nsview,nstextview,Objective C,Cocoa,Nsview,Nstextview,我试图放大包含NSTextView的NSScrollView,并始终将其置于内容的中心。NSTextView具有左/右插入,以保持单词包装的一致性,并将段落很好地保持在视图的中心 [NSScrollView scaleUnitSquareToSize:…]和设置放大率:…都有自己的怪癖和问题,但目前设置放大率似乎是一个更好的选择,因为它不是相对的 下面是发生的事情(还有其他奇怪的事情): 调整大小时,我会更新插图: CGFloat inset = self.textScrollView.fra

我试图放大包含
NSTextView
NSScrollView
,并始终将其置于内容的中心。
NSTextView
具有左/右插入,以保持单词包装的一致性,并将段落很好地保持在视图的中心

[NSScrollView scaleUnitSquareToSize:…]
设置放大率:…
都有自己的怪癖和问题,但目前设置放大率似乎是一个更好的选择,因为它不是相对的

下面是发生的事情(还有其他奇怪的事情):

调整大小时,我会更新插图:

CGFloat inset = self.textScrollView.frame.size.width / 2 - _documentWidth / 2;
self.textView.textContainerInset = NSMakeSize(inset, TEXT_INSET_TOP);
self.textView.textContainer.size = NSMakeSize(_documentWidth, self.textView.textContainer.size.height);
放大:

CGFloat magnification = [self.textScrollView magnification];
NSPoint center = NSMakePoint(self.textScrollView.frame.size.width / 2, self.textScrollView.frame.size.height / 2);

if (zoomIn) magnification += .05; else magnification -= .05;
[self.textScrollView setMagnification:magnification centeredAtPoint:center];
每样东西都能工作一段时间。有时,根据窗口从哪个窗口角调整大小,ScrollView会失去中心,我还没有找到一个解决方案来重新调整放大的
NSScrollView
视图的中心

放大后,在调整窗口大小时,布局约束也会被打破,尤其是当
textContainer
被剪裁出视图时,应用程序会崩溃,并出现以下错误:
***在-[NSISLinearExpression addVariable:covercient:],/Library/Caches/com.apple.xbs/Sources/Foundation/Foundation-1349.91/Layout.subproj/IncrementalSimplex/NSISLinearExpression.m:716中断言失败

一个问题可能是,我正在根据
UIScrollView
frame size设置插图,因为所包含的NSTextView的坐标在放大后似乎不是相对的,而是绝对的


有没有什么安全的方法可以放大这种视图,并使其始终以内容为中心?为什么我的约束被打破了呢?

我也遇到了类似的问题,不幸的是,我最终自己做了定心。以下是我的解决方案的一些亮点

  • 需要递归预防!(否则堆栈溢出:)
  • 创建一个不可绘制的NSView作为documentView,然后将可绘制视图添加为手动居中的子视图,并手动将框架设置为父视图的visibleRect
  • 重写visibleRect,如果它无效,则再次调用它,并进行调试以确保它有效
  • 缩放分层视图sux。您可以尝试使用NSTiledLayer,但我已经多次尝试并放弃了该解决方案
  • 代码如下:

    @interface FlippedParentView : NSView
    @end
    
    @implementation FlippedParentView
    - (BOOL) isFlipped { return YES; }
    @end
    
    
    
    
    - (void)awakeFromNib
    {
        [self resetMouseInfo];
        [[self window] setAcceptsMouseMovedEvents:YES];
        needsFullRedraw = YES;
        [self setAcceptsTouchEvents:YES];
    
        // problem: when zoomed-in, CALayer backed NSOpenGLView becomes too large
        // and hurts performance.
        // solution: create a fullsizeView for the NSScrollView to resize,
        // and make NSOpenGLView a subview.  Keep NSOpenGLView size the same as visibleRect,
        // positioning it as needed on the fullsizeView.
        NSScrollView *scrollvw = [self enclosingScrollView];
        [scrollvw setBackgroundColor:[NSColor darkStrokeColor]];
        fullsizeView = [[FlippedParentView alloc] initWithFrame: [self frame]];
        [scrollvw setDocumentView:fullsizeView];
        [fullsizeView setAutoresizesSubviews:NO];
        //printf("mask %d\n", [self autoresizingMask]);
        [fullsizeView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable | NSViewMinYMargin | NSViewMaxYMargin | NSViewMaxXMargin | NSViewMinXMargin];
        [self setAutoresizingMask: NSViewNotSizable];
        [fullsizeView addSubview:self];
    }
    
    - (NSRect) visibleRect
    {
        NSRect visRect = [super visibleRect];
        if ( visRect.size.width == 0 )
        {
            visRect = [[self superview] visibleRect];
            if ( visRect.size.width == 0 )
            {
                // this jacks up everything
                DUMP( @"bad visibleRect" );
            }
            visRect.origin = NSZeroPoint;
        }
        return visRect;
    }
    
    - (void) _my_zoom: (double)newZoom
    {
        mouseFocusPt = [self focusPt];
        NSRect oldVisRect = [[self superview] visibleRect];
        if ( newZoom < 1.0 )
            newZoom = 1.0;
        if ( newZoom > kZoomFactorMax ) newZoom = kZoomFactorMax;
    
        float xpct = (mouseFocusPt.x - oldVisRect.origin.x) /
        ( NSMaxX(oldVisRect) - oldVisRect.origin.x );
    
        float ypct = (mouseFocusPt.y  - oldVisRect.origin.y) /
        ( NSMaxY(oldVisRect) - oldVisRect.origin.y );
    
        float oldZoom = zoomFactor;
    
        zoomFactor = newZoom;
    
        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // Stay locked on users' relative mouse location, so user can zoom in and back out without
        // the view scrolling out from under the mouse location.
        NSPoint newFocusPt = NSMakePoint (mouseFocusPt.x * newZoom/oldZoom,
                                          mouseFocusPt.y * newZoom/oldZoom) ;
    
        NSRect myFrame = fullsizeFrame; // [self frame];
        float marginPercent = (myFrame.size.height - drawableSizeWithMargins.height) / drawableSizeWithMargins.height;
    
        [self updateContext];
    
        NSRect newVisRect;
        newVisRect.size = [self visibleRect].size;
        newVisRect.origin.x = (newFocusPt.x) - (xpct * newVisRect.size.width);
        //DLog( @"xpct %0.2f, zoomFactor %0.2f, newVisRect.origin.x %0.2f", xpct, zoomFactor, newVisRect.origin.x);
    
        myFrame = fullsizeFrame; // [self frame];
        float marginPercent2 = (myFrame.size.height - drawableSizeWithMargins.height) / drawableSizeWithMargins.height;
        float marginDiff = (marginPercent - marginPercent2) * drawableSizeWithMargins.height;
        newVisRect.origin.y = (newFocusPt.y ) - (ypct * newVisRect.size.height) - marginDiff;
        //DLog( @"ypct %0.2f, zoomFactor %0.2f, newVisRect.origin.y %0.2f", ypct, zoomFactor, newVisRect.origin.y);
        //DLog( @"marginPercent %0.2f newVisRect %@", marginPercent, NSStringFromRect(newVisRect) );
        if ( newVisRect.origin.x < 1 ) newVisRect.origin.x = 1;
        if ( newVisRect.origin.y < 1 ) newVisRect.origin.y = 1;
    
    
         //   NSLog( @"zoom scrollRectToVisible %@ bounds %@", NSStringFromRect(newVisRect), NSStringFromRect([[self superview] bounds]) );
        // if ( iUseMousePt || isSlider )
            [[self superview] scrollRectToVisible:newVisRect];
    }
    
    // - zoomFactor of 1.0 is defined as the zoomFactor needed to show entire selected context within visibleRect,
    //   including margins of 5% of the context size
    // - zoomFactor > 1.0 will make pixels look bigger (view a subsection of a larger total drawableSize)
    // - zoomFactor < 1.0 will make pixels look smaller (selectedContext size will be less than drawableSize)
    -(void)updateContext
    {
        static BOOL sRecursing = NO;
        if ( sRecursing ) return; // prevent recursion
        sRecursing = YES;
    
        //NSRect scrollRect = [[self superview]  frame];
        NSRect clipViewRect = [[[self enclosingScrollView] contentView] frame];
        NSRect visRect = [[self superview] visibleRect]; // careful... visibleRect is sometimes NSZeroRect
    
        float layoutWidth = clipViewRect.size.width;
        float layoutHeight = clipViewRect.size.height;
    
    
    
        marginPct = layoutHeight / (layoutHeight - (overlayViewMargin*2) );
    
        // Satisfy the constraints fully-zoomed-out case:
        //  1) the drawable rect is centered in the view with at margins.
        //     Allow for 5% margins (1.025 = 2.5% left, right, top, bottom)
        //  2) guarantee the drawable rect does not overlap the mini-map in upper right corner.
        NSRect baseRect = NSZeroRect;
        baseRect.size = visRect.size;
        NSRect drawableBaseRect = getCenteredRectFloat(baseRect, metaUnionRect.size );
    
        //drawableSizeWithMargins = nsIntegralSize( nsScaleSize( drawableBaseRect.size, zoomFactor ) );
        drawableSizeWithMargins = nsScaleSize( drawableBaseRect.size, zoomFactor );
    
        // drawableSize will NOT include the margins.  We loop until we've satisfied
        // the constraints above.
        drawableSize = drawableSizeWithMargins;
    
        do
        {
            NSSize shrunkSize;
            shrunkSize.width = layoutWidth / marginPct;
            shrunkSize.height = layoutHeight /  marginPct;
            //drawableSize = nsIntegralSize( nsScaleSize( drawableBaseRect.size, zoomFactor / marginPct ));
            drawableSize = nsScaleSize( drawableBaseRect.size, zoomFactor / marginPct );
    
            [self calculateMiniMapRect]; // get approx. size.  Will calculate once more below.
    
            NSRect shrunkRect = getCenteredRectNoScaling(baseRect, shrunkSize );
    
            // DLog( @"rough miniMapRect %@ shrunk %@", NSStringFromRect(miniMapRect), NSStringFromRect(shrunkRect));
    
            // make sure minimap doesn't overlap drawable when you scroll to top-left
            NSRect topMiniMapRect = miniMapRect;
            topMiniMapRect.origin.x -= visRect.origin.x;
            topMiniMapRect.origin.y = 0;
            if ( !NSIntersectsRect( topMiniMapRect, shrunkRect ) )
            {
                topMarginPercent = fabs(shrunkRect.origin.y - drawableBaseRect.origin.y)  / baseRect.size.height;
                break;
            }
    
            float topMarginOffset = shrunkRect.size.height + (baseRect.size.height * 0.025);
            shrunkRect.origin.y = NSMaxY(baseRect) - topMarginOffset;
    
            if ( !NSIntersectsRect( topMiniMapRect, shrunkRect ) )
            {
                topMarginPercent = fabs(shrunkRect.origin.y - drawableBaseRect.origin.y)  / baseRect.size.height;
                break;
            }
    
            marginPct *= 1.025;
        } while (1);
    
        fullsizeFrame.origin = NSZeroPoint;
        fullsizeFrame.size.width  = fmax(drawableSizeWithMargins.width, layoutWidth);
        fullsizeFrame.size.height = fmax(drawableSizeWithMargins.height, layoutHeight);
    
        [fullsizeView setFrame:fullsizeFrame];
    
        NSRect myNewFrame = [fullsizeView visibleRect];
        if (myNewFrame.size.width > 0)
           [self setFrame: myNewFrame]; //NSView
    
        sRecursing = NO;
    }
    
    @接口FlippedParentView:NSView
    @结束
    @实现FlippedParentView
    -(BOOL)被翻转{返回YES;}
    @结束
    -(无效)从NIB中唤醒
    {
    [自我重置鼠标信息];
    [[self window]setAcceptsMouseMovedEvents:是];
    needsFullRedraw=是;
    [自我设置接受接触事件:是];
    //问题:放大时,CALayer支持的NSOpenGLView变得太大
    //而且会影响性能。
    //解决方案:为NSScrollView创建一个fullsizeView以调整大小,
    //并使NSOpenGLView成为子视图。保持NSOpenGLView大小与visibleRect相同,
    //根据需要在fullsizeView上定位它。
    NSScrollView*scrollvw=[自封闭CrollView];
    [scrollvw setBackgroundColor:[NSColor darkStrokeColor]];
    fullsizeView=[[FlippedParentView alloc]initWithFrame:[self frame]];
    [scrollvw setDocumentView:fullsizeView];
    [fullsizeView SETAUTORESISSUBVIEWS:否];
    //printf(“掩码%d\n,[self autoresizingMask]);
    [fullsizeView setAutoresizingMask:NSVIEWHEIGHT SIZABLE | NSVIEWWIDTH SIZABLE | NSViewMinYMargin | NSVIEWMAXMARGIN | NSVIEWMAXMARGIN | NSViewMinXMargin];
    [self-setAutoresizingMask:nsViewNotSize];
    [fullsizeView addSubview:self];
    }
    -(NSRect)visibleRect
    {
    NSRect visRect=[super visibleRect];
    if(visRect.size.width==0)
    {
    visRect=[[self superview]visibleRect];
    if(visRect.size.width==0)
    {
    //这把一切都搞砸了
    转储(@“坏的visibleRect”);
    }
    visRect.origin=NSZeroPoint;
    }
    回归直观;
    }
    -(无效)\u我的\u缩放:(双)新缩放
    {
    mouseFocusPt=[自聚焦];
    NSRect oldVisRect=[[self superview]visibleRect];
    如果(新缩放<1.0)
    newZoom=1.0;
    如果(newZoom>kZoomFactorMax)newZoom=kZoomFactorMax;
    float xpct=(mousefocust.x-oldVisRect.origin.x)/
    (NSMaxX(oldVisRect)-oldVisRect.origin.x);
    浮点ypct=(mousefocust.y-oldVisRect.origin.y)/
    (NSMaxY(oldVisRect)-oldVisRect.origin.y);
    float oldZoom=zoomFactor;
    zoomFactor=newZoom;
    /////////////////////////////////////////////////////////////////////////////////////////////////////
    //保持锁定在用户的相对鼠标位置上,这样用户就可以在不使用鼠标的情况下进行放大和缩小
    //从鼠标位置下滚动出的视图。
    NSPoint newFocusPt=NSMakePoint(mousefocust.x*newZoom/oldZoom,
    鼠标焦点y*新缩放/旧缩放);
    NSRect myFrame=fullsizeFrame;//[self-frame];
    浮动边距百分比=(myFrame.size.height-drawableSizeWithMargins.height)/drawableSizeWithMargins.height;
    [自我更新文本];
    NSRect newVisRect;
    newVisRect.size=[self visibleRect].size;
    newVisRect.origin.x=(newFocusPt.x)-(xpct*newVisRect.size.width);
    //DLog(@“xpct%0.2f,zoomFactor%0.2f,newVisRect.origin.x%0.2f”,xpct,zoomFactor,newVisRect.origin.x);
    myFrame=fullsizeFrame;//[self-frame];
    float marginPercent2=(myFrame.size.height-drawableSizeWithMargins.height)/drawableSizeWithMargins.height;
    浮动保证金贴现=(保证金百分比-保证金百分比2)*可提取尺寸与保证金高度;
    newVisRect.origin.y=(newFocusPt.y)-(ypct*newVisRect.size.height)-marginDiff;
    //DLog(@“ypct%0.2f,zoomFactor%0.2f,NewVistrect.origin.y%0.2f”,ypct,zoomFactor,NewVistrect.origin.y);
    //DLog(@“marginPercent%0.2f newVisRect%@”,marginPercent,NSStringFromRect(newVisRect));
    如果(newVisRect.origin.x<1)newVisRect.origin.x=1;
    if(newVisRect.origin.y<1