Implement bootstrapping auto layout

This commit is contained in:
Benjamin Johnson 2023-02-26 13:28:15 +11:00
parent 829069af34
commit 93769f3a52
8 changed files with 259 additions and 21 deletions

View file

@ -30,6 +30,7 @@
#import <Foundation/NSKeyedArchiver.h>
#import <AppKit/NSLayoutAnchor.h>
#import <AppKit/NSView.h>
#import <AppKit/NSWindow.h>
@class NSControl, NSAnimation, NSArray, NSMutableArray, NSDictionary;
@ -183,6 +184,14 @@ APPKIT_EXPORT_CLASS
@end
@interface NSWindow (NSConstraintBasedLayoutCoreMethods)
- (void) _bootstrapAutoLayout;
- (void) layoutIfNeeded;
@end
#if defined(__cplusplus)
}
#endif

View file

@ -53,6 +53,7 @@
@class NSScrollView;
@class NSView;
@class NSWindow;
@class GSAutoLayoutEngine;
typedef NSInteger NSTrackingRectTag;
typedef NSInteger NSToolTipTag;
@ -186,6 +187,7 @@ PACKAGE_SCOPE
NSUInteger _autoresizingMask;
NSFocusRingType _focusRingType;
NSRect _autoresizingFrameError;
GSAutoLayoutEngine *_layoutEngine;
}
/*

View file

@ -356,6 +356,7 @@ GSXibLoading.m \
GSXibKeyedUnarchiver.m \
GSXib5KeyedUnarchiver.m \
GSHelpAttachment.m \
GSAutoLayoutEngine.m \
GSAutoLayoutVFLParser.m
# Turn off NSMenuItem warning that NSMenuItem conforms to <NSObject>,
@ -671,7 +672,8 @@ GSXibElement.h \
GSXibLoading.h \
GSXibKeyedUnarchiver.h \
GSHelpAttachment.h \
GSAutoLayoutVFLParser.h
GSAutoLayoutVFLParser.h \
GSAutoLayoutEngine.h
libgnustep-gui_HEADER_FILES = ${GUI_HEADERS}

View file

@ -0,0 +1,48 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 28-2-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "AppKit/NSLayoutConstraint.h"
#import <Foundation/Foundation.h>
@class NSView;
@class NSLayoutConstraint;
#ifndef _GS_AUTO_LAYOUT_ENGINE_H
#define _GS_AUTO_LAYOUT_ENGINE_H
@interface GSAutoLayoutEngine : NSObject
- (void) addConstraint: (NSLayoutConstraint *)constraint;
- (void) addConstraints: (NSArray *)constraints;
- (void) removeConstraint: (NSLayoutConstraint *)constraint;
- (void) removeConstraints: (NSArray *)constraints;
- (NSRect) alignmentRectForView: (NSView *)view;
- (NSArray *) constraintsForView: (NSView *)view;
@end
#endif

View file

@ -0,0 +1,60 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 28-2-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSAutoLayoutEngine.h"
#include "AppKit/NSLayoutConstraint.h"
@implementation GSAutoLayoutEngine
- (void) addConstraint: (NSLayoutConstraint *)constraint
{
// FIXME Add constraint to solver
}
- (void) addConstraints: (NSArray *)constraints
{
// FIXME Add constraints to solver
}
- (void) removeConstraint: (NSLayoutConstraint *)constraint
{
// FIXME Remove constraint from solver
}
- (void) removeConstraints: (NSArray *)constraints
{
// FIXME Remove constraints from solver
}
- (NSRect) alignmentRectForView: (NSView *)view
{
// FIXME Get alignment rect for view from solver
return NSMakeRect (0, 0, 0, 0);
}
- (NSArray *) constraintsForView: (NSView *)view
{
// FIXME Get constraints for view
return [NSArray array];
}
@end

View file

@ -36,6 +36,7 @@
#import "NSAutoresizingMaskLayoutConstraint.h"
#import "GSFastEnumeration.h"
#import "GSAutoLayoutVFLParser.h"
#import "GSAutoLayoutEngine.h"
static NSMutableArray *activeConstraints = nil;
// static NSNotificationCenter *nc = nil;
@ -652,16 +653,92 @@ static NSMutableArray *activeConstraints = nil;
@implementation NSView (NSConstraintBasedLayoutInstallingConstraints)
- (void) _bootstrapAutoLayout
{
if ([self window])
{
[[self window] _bootstrapAutoLayout];
}
else
{
[self _initializeLayoutEngine];
}
}
- (void) addConstraint: (NSLayoutConstraint *)constraint
{
// FIXME: Implement adding constraint to layout engine
if (![self _layoutEngine])
{
[self _bootstrapAutoLayout];
}
[[self _layoutEngine] addConstraint: constraint];
}
- (void) addConstraints: (NSArray*)constraints
{
FOR_IN (NSLayoutConstraint*, constraint, constraints)
[self addConstraint: constraint];
END_FOR_IN (constraints);
if (![self _layoutEngine])
{
[self _bootstrapAutoLayout];
}
[[self _layoutEngine] addConstraints: constraints];
}
- (void) removeConstraint: (NSLayoutConstraint *)constraint
{
if (![self _layoutEngine])
{
return;
}
[[self _layoutEngine] removeConstraint: constraint];
}
- (void) removeConstraints: (NSArray *)constraints
{
if (![self _layoutEngine])
{
return;
}
[[self _layoutEngine] removeConstraints: constraints];
}
- (NSArray*) constraints
{
GSAutoLayoutEngine *engine = [self _layoutEngine];
if (!engine)
{
return [NSArray array];
}
return [engine constraintsForView: self];
}
- (void) _initializeLayoutEngine
{
[self _setLayoutEngine: [[GSAutoLayoutEngine alloc] init]];
}
@end
@implementation NSWindow (NSConstraintBasedLayoutCoreMethods)
- (void) layoutIfNeeded
{
[self updateConstraintsIfNeeded];
[[self contentView] _layoutViewAndSubViews];
}
- (void) updateConstraintsIfNeeded
{
[[self contentView] updateConstraintsForSubtreeIfNeeded];
}
- (void) _bootstrapAutoLayout
{
[[[self contentView] superview] _initializeLayoutEngine];
}
@end

View file

@ -79,6 +79,7 @@
#import "GSBindingHelpers.h"
#import "GSFastEnumeration.h"
#import "GSGuiPrivate.h"
#import "GSAutoLayoutEngine.h"
#import "NSViewPrivate.h"
/*
@ -635,6 +636,7 @@ GSSetDragTypes(NSView* obj, NSArray *types)
_needsUpdateConstraints = YES;
_translatesAutoresizingMaskIntoConstraints = YES;
_layoutEngine = nil;
return self;
}
@ -768,6 +770,11 @@ GSSetDragTypes(NSView* obj, NSArray *types)
[self unregisterDraggedTypes];
[self releaseGState];
if (_layoutEngine && !_super_view)
{
RELEASE(_layoutEngine);
}
[super dealloc];
}
@ -826,6 +833,8 @@ GSSetDragTypes(NSView* obj, NSArray *types)
index += 1;
}
[aView _setLayoutEngine: [self _layoutEngine]];
[aView _viewWillMoveToWindow: _window];
[aView _viewWillMoveToSuperview: self];
[aView setNextResponder: self];
@ -5140,7 +5149,17 @@ static NSView* findByTag(NSView *view, NSInteger aTag, NSUInteger *level)
- (void) layout
{
// FIXME: Implement asking layout engine for the alignment rect of each subview and set the alignment rect of each sub view
if (![self _layoutEngine])
{
return;
}
NSArray *subviews = [self subviews];
FOR_IN (NSView *, subview, subviews)
NSRect subviewAlignmentRect =
[[self _layoutEngine] alignmentRectForView: subview];
[subview setFrame: subviewAlignmentRect];
END_FOR_IN (subviews);
}
- (void) layoutSubtreeIfNeeded
@ -5149,20 +5168,6 @@ static NSView* findByTag(NSView *view, NSInteger aTag, NSUInteger *level)
[self _layoutViewAndSubViews];
}
- (void) _layoutViewAndSubViews
{
if (_needsLayout)
{
[self layout];
_needsLayout = NO;
}
NSArray *subviews = [self subviews];
FOR_IN (NSView *, subview, subviews)
[subview _layoutViewAndSubViews];
END_FOR_IN (subviews);
}
- (void) setNeedsLayout: (BOOL) needsLayout
{
if (!needsLayout)
@ -5212,6 +5217,35 @@ static NSView* findByTag(NSView *view, NSInteger aTag, NSUInteger *level)
_needsUpdateConstraints = needsUpdateConstraints;
}
- (void) _layoutViewAndSubViews
{
if (_needsLayout)
{
[self layout];
_needsLayout = NO;
}
NSArray *subviews = [self subviews];
FOR_IN (NSView *, subview, subviews)
[subview _layoutViewAndSubViews];
END_FOR_IN (subviews);
}
- (GSAutoLayoutEngine*) _layoutEngine
{
return _layoutEngine;
}
- (void) _setLayoutEngine: (GSAutoLayoutEngine *)engine
{
_layoutEngine = engine;
NSArray *subviews = [self subviews];
FOR_IN (NSView *, subview, subviews)
[subview _setLayoutEngine: engine];
END_FOR_IN (subviews);
}
@end
@implementation NSView (__NSViewPrivateMethods__)

View file

@ -42,6 +42,12 @@
- (void) _setNeedsUpdateConstraints: (BOOL)needsUpdateConstraints;
- (void) _layoutViewAndSubViews;
- (GSAutoLayoutEngine*) _layoutEngine;
- (void) _setLayoutEngine: (GSAutoLayoutEngine*)engine;
@end
#endif // _GNUstep_H_NSViewPrivate