mirror of
https://github.com/textmate/textmate.git
synced 2026-01-21 04:38:13 -05:00
Remove legacy code
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
#include "box.h"
|
||||
|
||||
struct OakResizeInfo
|
||||
{
|
||||
int width, height;
|
||||
enum { kTopLeft, kTopRight, kBottomLeft, kBottomRight } corner;
|
||||
enum { kWidth, kHeight } adjustable;
|
||||
};
|
||||
|
||||
@interface OakLayoutView : NSView
|
||||
{
|
||||
box_t* box;
|
||||
std::map<NSView*, box_t*> views;
|
||||
std::multimap<NSView*, OakResizeInfo> resize_info;
|
||||
}
|
||||
- (void)addView:(NSView*)aView;
|
||||
- (void)addView:(NSView*)aView atEdge:(NSRectEdge)anEdge ofView:(NSView*)otherView;
|
||||
- (void)removeView:(NSView*)aView;
|
||||
- (void)setLocked:(BOOL)flag forView:(NSView*)aView;
|
||||
- (void)addResizeInfo:(OakResizeInfo)info forView:(NSView*)aView;
|
||||
- (void)removeResizeInfoForView:(NSView*)aView;
|
||||
@end
|
||||
@@ -1,342 +0,0 @@
|
||||
#import "OakLayoutView.h"
|
||||
#import <oak/CocoaSTL.h>
|
||||
#import <oak/debug.h>
|
||||
|
||||
OAK_DEBUG_VAR(OakLayoutView);
|
||||
|
||||
enum edge_t { kLeftEdge, kTopEdge, kRightEdge, kBottomEdge };
|
||||
|
||||
struct OakResizeHandle
|
||||
{
|
||||
box_t* box;
|
||||
edge_t edge;
|
||||
int distance;
|
||||
|
||||
explicit operator bool () const { return box; }
|
||||
};
|
||||
|
||||
static void add_cursors (box_t* box, NSView* view)
|
||||
{
|
||||
if(!box || box->children().empty())
|
||||
return;
|
||||
|
||||
std::vector<box_t*> const& children = box->children();
|
||||
for(size_t i = 0; i < children.size() - 1; ++i)
|
||||
{
|
||||
rect_t prev = children[i]->bounds(), next = children[i+1]->bounds();
|
||||
rect_t r = box->horizontal() ? rect_t(prev.x1 - 2, next.x0 + 2, prev.y0, prev.y1) : rect_t(prev.x0, prev.x1, prev.y1 - 2, next.y0 + 2);
|
||||
[view addCursorRect:NSMakeRect(r.x0, r.y0, r.width(), r.height()) cursor:box->horizontal() ? [NSCursor resizeLeftRightCursor] : [NSCursor resizeUpDownCursor]];
|
||||
}
|
||||
|
||||
iterate(child, children)
|
||||
add_cursors(*child, view);
|
||||
}
|
||||
|
||||
static void draw_thumbs (box_t* box, NSView* view)
|
||||
{
|
||||
if(!box || box->children().empty())
|
||||
return;
|
||||
|
||||
std::vector<box_t*> const& children = box->children();
|
||||
for(size_t i = 0; i < children.size() - 1; ++i)
|
||||
{
|
||||
rect_t prev = children[i]->bounds(), next = children[i+1]->bounds();
|
||||
rect_t r = box->horizontal() ? rect_t(prev.x1, next.x0, prev.y0, prev.y1) : rect_t(prev.x0, prev.x1, prev.y1, next.y0);
|
||||
NSRectFill(NSMakeRect(r.x0, r.y0, r.width(), r.height()));
|
||||
}
|
||||
|
||||
iterate(child, children)
|
||||
draw_thumbs(*child, view);
|
||||
}
|
||||
|
||||
static OakResizeHandle find_resize_info (box_t* box, int x, int y)
|
||||
{
|
||||
if(!box || box->children().empty())
|
||||
return (OakResizeHandle){ NULL };
|
||||
|
||||
std::vector<box_t*> const& children = box->children();
|
||||
for(ssize_t i = 0; i < children.size() - 1; ++i)
|
||||
{
|
||||
rect_t prev = children[i]->bounds(), next = children[i+1]->bounds();
|
||||
rect_t r = box->horizontal() ? rect_t(prev.x1 - 2, next.x0 + 2, prev.y0, prev.y1) : rect_t(prev.x0, prev.x1, prev.y1 - 2, next.y0 + 2);
|
||||
if(r.contains(x, y))
|
||||
return (OakResizeHandle){ children[i], box->horizontal() ? kRightEdge : kBottomEdge, box->horizontal() ? prev.x1 - x : prev.y1 - y };
|
||||
}
|
||||
|
||||
iterate(child, children)
|
||||
{
|
||||
if(OakResizeHandle res = find_resize_info(*child, x, y))
|
||||
return res;
|
||||
}
|
||||
|
||||
return (OakResizeHandle){ NULL };
|
||||
}
|
||||
|
||||
static bool horizontal_edge (NSRectEdge edge)
|
||||
{
|
||||
return edge == NSMinXEdge || edge == NSMaxXEdge;
|
||||
}
|
||||
|
||||
static box_t* add_box (box_t* newBox, box_t* container, NSRectEdge edge, box_t const* otherBox)
|
||||
{
|
||||
if(!container)
|
||||
return newBox;
|
||||
|
||||
if(otherBox && otherBox != container)
|
||||
{
|
||||
std::vector<box_t*>& children = container->children();
|
||||
iterate(child, children)
|
||||
*child = add_box(newBox, *child, edge, otherBox);
|
||||
return container;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(container->children().empty() || container->horizontal() != horizontal_edge(edge))
|
||||
{
|
||||
box_t* wrapper = new box_t(horizontal_edge(edge) ? 0 : container->width(), horizontal_edge(edge) ? container->height() : 0, 0, 0, false, horizontal_edge(edge));
|
||||
wrapper->push_back(container);
|
||||
container = wrapper;
|
||||
}
|
||||
|
||||
rect_t r = container->bounds();
|
||||
switch(edge)
|
||||
{
|
||||
case NSMinXEdge: r.x0 += newBox->width() + kViewSpacing; newBox->set_height(container->height()); break;
|
||||
case NSMinYEdge: r.y0 += newBox->height() + kViewSpacing; newBox->set_width(container->width()); break;
|
||||
case NSMaxXEdge: r.x1 -= newBox->width() + kViewSpacing; newBox->set_height(container->height()); break;
|
||||
case NSMaxYEdge: r.y1 -= newBox->height() + kViewSpacing; newBox->set_width(container->width()); break;
|
||||
}
|
||||
|
||||
container->set_size(r);
|
||||
if(edge == NSMinXEdge || edge == NSMinYEdge)
|
||||
container->push_front(newBox);
|
||||
else container->push_back(newBox);
|
||||
container->freeze_layout();
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
@implementation OakLayoutView
|
||||
- (void)repositionSubviews
|
||||
{
|
||||
for(NSView* view in [self subviews])
|
||||
{
|
||||
std::map<NSView*, box_t*>::const_iterator it = views.find(view);
|
||||
ASSERT(it != views.end());
|
||||
[view setFrame:NSMakeRect(it->second->x0(), it->second->y0(), it->second->width(), it->second->height())];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setLocked:(BOOL)flag forView:(NSView*)aView
|
||||
{
|
||||
std::map<NSView*, box_t*>::iterator it = views.find(aView);
|
||||
ASSERT(it != views.end());
|
||||
it->second->set_locked(flag);
|
||||
}
|
||||
|
||||
- (void)addView:(NSView*)aView atEdge:(NSRectEdge)anEdge ofView:(NSView*)otherView
|
||||
{
|
||||
std::map<NSView*, box_t*>::const_iterator it = views.find(otherView);
|
||||
box_t const* otherBox = it != views.end() ? it->second : NULL;
|
||||
box_t* newBox = new box_t(NSWidth(aView.frame), NSHeight(aView.frame));
|
||||
|
||||
box = add_box(newBox, box, anEdge, otherBox);
|
||||
box->set_size(rect_t(0, NSWidth(self.frame), 0, NSHeight(self.frame)));
|
||||
box->freeze_layout();
|
||||
|
||||
views.insert(std::make_pair(aView, newBox));
|
||||
|
||||
[self addSubview:aView];
|
||||
[self repositionSubviews];
|
||||
[[self window] invalidateCursorRectsForView:self];
|
||||
|
||||
// [self setNeedsDisplay:YES];
|
||||
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidResize:) name:NSViewFrameDidChangeNotification object:aView];
|
||||
}
|
||||
|
||||
- (void)removeView:(NSView*)aView
|
||||
{
|
||||
std::map<NSView*, box_t*>::iterator it = views.find(aView);
|
||||
ASSERT(it != views.end());
|
||||
|
||||
box = box->erase(it->second);
|
||||
box->freeze_layout();
|
||||
views.erase(it);
|
||||
[self removeResizeInfoForView:aView];
|
||||
[aView removeFromSuperview];
|
||||
[self repositionSubviews];
|
||||
[[self window] invalidateCursorRectsForView:self];
|
||||
}
|
||||
|
||||
- (void)resetCursorRects
|
||||
{
|
||||
add_cursors(box, self);
|
||||
|
||||
iterate(pair, resize_info)
|
||||
{
|
||||
NSRect r = pair->first.frame;
|
||||
|
||||
int x0, y0;
|
||||
switch(pair->second.corner)
|
||||
{
|
||||
case OakResizeInfo::kTopLeft: x0 = NSMinX(r); y0 = NSMinY(r); break;
|
||||
case OakResizeInfo::kTopRight: x0 = NSMaxX(r); y0 = NSMinY(r); break;
|
||||
case OakResizeInfo::kBottomLeft: x0 = NSMinX(r); y0 = NSMaxY(r); break;
|
||||
case OakResizeInfo::kBottomRight: x0 = NSMaxX(r); y0 = NSMaxY(r); break;
|
||||
}
|
||||
|
||||
int x1 = x0 + pair->second.width;
|
||||
int y1 = y0 + pair->second.height;
|
||||
rect_t rect(std::min(x0, x1), std::max(x0, x1), std::min(y0, y1), std::max(y0, y1));
|
||||
|
||||
[self addCursorRect:NSMakeRect(rect.x0, rect.y0, rect.width(), rect.height()) cursor:pair->second.adjustable == OakResizeInfo::kWidth ? [NSCursor resizeLeftRightCursor] : [NSCursor resizeUpDownCursor]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resizeSubviewsWithOldSize:(NSSize)oldSize
|
||||
{
|
||||
int w = std::max<int>(NSWidth(self.frame), box->min_width());
|
||||
int h = std::max<int>(NSHeight(self.frame), box->min_height());
|
||||
box->set_size(rect_t(0, w, 0, h));
|
||||
[self repositionSubviews];
|
||||
}
|
||||
|
||||
- (BOOL)isFlipped
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)aRect
|
||||
{
|
||||
[[NSColor lightGrayColor] set];
|
||||
draw_thumbs(box, self);
|
||||
}
|
||||
|
||||
- (OakResizeHandle)findResizeHandle:(NSPoint)pos
|
||||
{
|
||||
int x = (int)round(pos.x), y = (int)round(pos.y);
|
||||
if(OakResizeHandle res = find_resize_info(box, x, y))
|
||||
return res;
|
||||
|
||||
iterate(pair, resize_info)
|
||||
{
|
||||
NSRect r = pair->first.frame;
|
||||
|
||||
int x0, y0;
|
||||
edge_t edge = kLeftEdge; // avoid compiler warning
|
||||
switch(pair->second.corner)
|
||||
{
|
||||
case OakResizeInfo::kTopLeft: x0 = NSMinX(r); y0 = NSMinY(r); edge = pair->second.adjustable == OakResizeInfo::kWidth ? kLeftEdge : kTopEdge; break;
|
||||
case OakResizeInfo::kTopRight: x0 = NSMaxX(r); y0 = NSMinY(r); edge = pair->second.adjustable == OakResizeInfo::kWidth ? kRightEdge : kTopEdge; break;
|
||||
case OakResizeInfo::kBottomLeft: x0 = NSMinX(r); y0 = NSMaxY(r); edge = pair->second.adjustable == OakResizeInfo::kWidth ? kLeftEdge : kBottomEdge; break;
|
||||
case OakResizeInfo::kBottomRight: x0 = NSMaxX(r); y0 = NSMaxY(r); edge = pair->second.adjustable == OakResizeInfo::kWidth ? kRightEdge : kBottomEdge; break;
|
||||
}
|
||||
|
||||
int x1 = x0 + pair->second.width;
|
||||
int y1 = y0 + pair->second.height;
|
||||
|
||||
if(rect_t(std::min(x0, x1), std::max(x0, x1), std::min(y0, y1), std::max(y0, y1)).contains(x, y))
|
||||
{
|
||||
int distance = 0;
|
||||
switch(edge)
|
||||
{
|
||||
case kLeftEdge: distance = x - std::min(x0, x1); break;
|
||||
case kRightEdge: distance = std::max(x0, x1) - x; break;
|
||||
case kTopEdge: distance = y - std::min(y0, y1); break;
|
||||
case kBottomEdge: distance = std::max(y0, y1) - y; break;
|
||||
}
|
||||
return (OakResizeHandle){ views[pair->first], edge, distance };
|
||||
}
|
||||
}
|
||||
|
||||
return (OakResizeHandle){ NULL };
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent*)anEvent
|
||||
{
|
||||
NSPoint pos = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
D(DBF_OakLayoutView, bug("%.0f, %.0f\n", pos.x, pos.y););
|
||||
if(OakResizeHandle handle = [self findResizeHandle:pos])
|
||||
{
|
||||
box_t* clicked = handle.box;
|
||||
edge_t edge = handle.edge;
|
||||
int distance = handle.distance;
|
||||
|
||||
box->freeze_layout();
|
||||
D(DBF_OakLayoutView, bug("start resize tracking of box %s\n", to_s(clicked->bounds()).c_str()););
|
||||
while((anEvent = [[self window] nextEventMatchingMask:NSLeftMouseDraggedMask | NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]) && [anEvent type] != NSLeftMouseUp)
|
||||
{
|
||||
rect_t bounds = clicked->bounds();
|
||||
pos = [self convertPoint:[anEvent locationInWindow] fromView:nil];
|
||||
switch(edge)
|
||||
{
|
||||
case kLeftEdge: bounds.x0 = pos.x - distance; break;
|
||||
case kRightEdge: bounds.x1 = pos.x + distance; break;
|
||||
case kTopEdge: bounds.y0 = pos.y - distance; break;
|
||||
case kBottomEdge: bounds.y1 = pos.y + distance; break;
|
||||
}
|
||||
box->resize(clicked, bounds);
|
||||
box->freeze_layout();
|
||||
[self repositionSubviews];
|
||||
[[self window] invalidateCursorRectsForView:self];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
D(DBF_OakLayoutView, bug("stop resize tracking\n"););
|
||||
[[self window] discardEventsMatchingMask:NSAnyEventMask beforeEvent:anEvent];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [super mouseDown:anEvent];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addView:(NSView*)aView
|
||||
{
|
||||
[self addView:aView atEdge:NSMaxYEdge ofView:nil];
|
||||
}
|
||||
|
||||
- (void)addResizeInfo:(OakResizeInfo)info forView:(NSView*)aView
|
||||
{
|
||||
resize_info.insert(std::make_pair(aView, info));
|
||||
}
|
||||
|
||||
- (void)removeResizeInfoForView:(NSView*)aView
|
||||
{
|
||||
resize_info.erase(resize_info.lower_bound(aView), resize_info.upper_bound(aView));
|
||||
}
|
||||
|
||||
- (void)performClose:(id)sender
|
||||
{
|
||||
NSView* view = (NSView*)[[self window] firstResponder];
|
||||
if(![view isKindOfClass:[NSView class]])
|
||||
return;
|
||||
|
||||
while(view && [view superview] != self)
|
||||
view = [view superview];
|
||||
|
||||
if(view)
|
||||
[NSApp sendAction:@selector(performCloseSplit:) to:nil from:view];
|
||||
else [[self nextResponder] tryToPerform:_cmd with:sender];
|
||||
}
|
||||
|
||||
- (NSView*)hitTest:(NSPoint)aPoint
|
||||
{
|
||||
D(DBF_OakLayoutView, bug("%s\n", [NSStringFromPoint(aPoint) UTF8String]););
|
||||
if([self findResizeHandle:[self convertPoint:aPoint fromView:[self superview]]])
|
||||
{
|
||||
D(DBF_OakLayoutView, bug("found resize handle\n"););
|
||||
return self;
|
||||
}
|
||||
|
||||
D(DBF_OakLayoutView, bug("call super\n"););
|
||||
ASSERT([super respondsToSelector:@selector(hitTest:)]);
|
||||
return [super hitTest:aPoint];
|
||||
}
|
||||
@end
|
||||
@@ -1,353 +0,0 @@
|
||||
#include "box.h"
|
||||
#include <oak/debug.h>
|
||||
|
||||
int kViewSpacing = 1;
|
||||
|
||||
box_t::box_t (int width, int height, int minWidth, int minHeight, bool locked, bool horizontal) : _bounds(0, width, 0, height), _min_width(minWidth), _min_height(minHeight), _ideal_width(width), _ideal_height(height), _locked(locked), _horizontal_layout(horizontal)
|
||||
{
|
||||
ASSERT_LE(_min_width, _bounds.width());
|
||||
ASSERT_LE(_min_height, _bounds.height());
|
||||
}
|
||||
|
||||
void box_t::push_front (box_t* box)
|
||||
{
|
||||
ASSERT_LE(box->min_width(), box->width());
|
||||
ASSERT_LE(box->min_height(), box->height());
|
||||
|
||||
rect_t bounds = _bounds;
|
||||
if(_horizontal_layout)
|
||||
{
|
||||
bounds.move_to(_bounds.x0 - box->width() - kViewSpacing, _bounds.y0);
|
||||
bounds.set_width(box->width());
|
||||
bounds.set_height(std::max(height(), box->min_height()));
|
||||
box->set_size(bounds);
|
||||
_bounds.x0 = box->x0();
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds.move_to(_bounds.x0, _bounds.y0 - box->height() - kViewSpacing);
|
||||
bounds.set_width(std::max(width(), box->min_width()));
|
||||
bounds.set_height(box->height());
|
||||
box->set_size(bounds);
|
||||
_bounds.y0 = box->y0();
|
||||
}
|
||||
_children.insert(_children.begin(), box);
|
||||
}
|
||||
|
||||
void box_t::push_back (box_t* box)
|
||||
{
|
||||
ASSERT_LE(box->min_width(), box->width());
|
||||
ASSERT_LE(box->min_height(), box->height());
|
||||
|
||||
rect_t bounds = _bounds;
|
||||
if(_horizontal_layout)
|
||||
{
|
||||
bounds.move_to(_bounds.x1 + kViewSpacing, _bounds.y0);
|
||||
bounds.set_width(box->width());
|
||||
bounds.set_height(std::max(height(), box->min_height()));
|
||||
box->set_size(bounds);
|
||||
_bounds.set_width(_bounds.width() + kViewSpacing + box->width());
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds.move_to(_bounds.x0, _bounds.y1 + kViewSpacing);
|
||||
bounds.set_width(std::max(width(), box->min_width()));
|
||||
bounds.set_height(box->height());
|
||||
box->set_size(bounds);
|
||||
_bounds.set_height(_bounds.height() + kViewSpacing + box->height());
|
||||
}
|
||||
_children.push_back(box);
|
||||
}
|
||||
|
||||
box_t* box_t::erase (box_t* box)
|
||||
{
|
||||
if(box == this)
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(_children.empty())
|
||||
return this;
|
||||
|
||||
std::vector<box_t*> newChildren;
|
||||
iterate(child, _children)
|
||||
*child = (*child)->erase(box);
|
||||
|
||||
for(size_t i = 0; i < _children.size(); ++i)
|
||||
{
|
||||
if(_children[i] == NULL)
|
||||
{
|
||||
if(_horizontal_layout)
|
||||
{
|
||||
if(i != 0 && i+1 != _children.size())
|
||||
{
|
||||
rect_t left = _children[i-1]->bounds(), right = _children[i+1]->bounds();
|
||||
int x = (left.x1 + right.x0) / 2;
|
||||
left.x1 = x;
|
||||
right.x0 = x + kViewSpacing;
|
||||
_children[i-1]->set_size(left);
|
||||
_children[i+1]->set_size(right);
|
||||
}
|
||||
else if(i != 0)
|
||||
{
|
||||
rect_t left = _children[i-1]->bounds();
|
||||
left.x1 = _bounds.x1;
|
||||
_children[i-1]->set_size(left);
|
||||
}
|
||||
else if(i+1 != _children.size())
|
||||
{
|
||||
rect_t right = _children[i+1]->bounds();
|
||||
right.x0 = _bounds.x0;
|
||||
_children[i+1]->set_size(right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i != 0 && i+1 != _children.size())
|
||||
{
|
||||
rect_t left = _children[i-1]->bounds(), right = _children[i+1]->bounds();
|
||||
int y = (left.y1 + right.y0) / 2;
|
||||
left.y1 = y;
|
||||
right.y0 = y + kViewSpacing;
|
||||
_children[i-1]->set_size(left);
|
||||
_children[i+1]->set_size(right);
|
||||
}
|
||||
else if(i != 0)
|
||||
{
|
||||
rect_t left = _children[i-1]->bounds();
|
||||
left.y1 = _bounds.y1;
|
||||
_children[i-1]->set_size(left);
|
||||
}
|
||||
else if(i+1 != _children.size())
|
||||
{
|
||||
rect_t right = _children[i+1]->bounds();
|
||||
right.y0 = _bounds.y0;
|
||||
_children[i+1]->set_size(right);
|
||||
}
|
||||
}
|
||||
|
||||
_children.erase(_children.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(_children.empty())
|
||||
{
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
else if(_children.size() == 1)
|
||||
{
|
||||
box_t* res = _children.back();
|
||||
delete this;
|
||||
return res;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
box_t* box_t::find (int x, int y)
|
||||
{
|
||||
if(!_bounds.contains(x, y))
|
||||
return NULL;
|
||||
|
||||
iterate(child, _children)
|
||||
{
|
||||
if(box_t* res = (*child)->find(x, y))
|
||||
return res;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
struct size_info_t
|
||||
{
|
||||
size_info_t (size_t minSize, size_t extraSize, bool locked) : size(minSize), extra_size(extraSize), locked(locked) { }
|
||||
|
||||
size_t size;
|
||||
size_t extra_size;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
static void layout (std::vector<size_info_t>& sizes, int size)
|
||||
{
|
||||
int idealWidth = 0;
|
||||
int lockedWidth = 0;
|
||||
int flexibleWidth = 0;
|
||||
iterate(it, sizes)
|
||||
{
|
||||
idealWidth += it->extra_size;
|
||||
if(it->locked)
|
||||
lockedWidth += it->extra_size;
|
||||
else flexibleWidth += it->extra_size;
|
||||
size -= it->size;
|
||||
}
|
||||
|
||||
if(size >= lockedWidth)
|
||||
{
|
||||
size -= lockedWidth;
|
||||
int counter = 0;
|
||||
iterate(it, sizes)
|
||||
{
|
||||
if(it->locked)
|
||||
{
|
||||
it->size += it->extra_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->size += size * (counter + it->extra_size) / flexibleWidth - size * counter / flexibleWidth;
|
||||
counter += it->extra_size;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(counter, flexibleWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
int counter = 0;
|
||||
iterate(it, sizes)
|
||||
{
|
||||
if(it->locked)
|
||||
{
|
||||
it->size += size * (counter + it->extra_size) / lockedWidth - size * counter / lockedWidth;
|
||||
counter += it->extra_size;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(counter, lockedWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void box_t::set_size (rect_t const& newBounds)
|
||||
{
|
||||
ASSERT_GE(newBounds.width(), min_width());
|
||||
ASSERT_GE(newBounds.height(), min_height());
|
||||
|
||||
if(_children.empty())
|
||||
{
|
||||
_bounds = newBounds;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<size_info_t> sizes;
|
||||
if(_horizontal_layout)
|
||||
{
|
||||
iterate(child, _children)
|
||||
sizes.push_back(size_info_t((*child)->min_width(), (*child)->_ideal_width - (*child)->min_width(), (*child)->locked()));
|
||||
layout(sizes, newBounds.width() - kViewSpacing * (_children.size() - 1));
|
||||
|
||||
int x = newBounds.x0;
|
||||
for(size_t i = 0; i < _children.size(); ++i)
|
||||
{
|
||||
_children[i]->set_size(rect_t(x, x + sizes[i].size, newBounds.y0, newBounds.y1));
|
||||
x += sizes[i].size + kViewSpacing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iterate(child, _children)
|
||||
sizes.push_back(size_info_t((*child)->min_height(), (*child)->_ideal_height - (*child)->min_height(), (*child)->locked()));
|
||||
layout(sizes, newBounds.height() - kViewSpacing * (_children.size() - 1));
|
||||
|
||||
int y = newBounds.y0;
|
||||
for(size_t i = 0; i < _children.size(); ++i)
|
||||
{
|
||||
_children[i]->set_size(rect_t(newBounds.x0, newBounds.x1, y, y + sizes[i].size));
|
||||
y += sizes[i].size + kViewSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
_bounds = newBounds;
|
||||
}
|
||||
|
||||
void box_t::freeze_layout ()
|
||||
{
|
||||
iterate(child, _children)
|
||||
(*child)->freeze_layout();
|
||||
|
||||
_ideal_width = width();
|
||||
_ideal_height = height();
|
||||
}
|
||||
|
||||
bool box_t::resize (box_t* box, rect_t const& newRect)
|
||||
{
|
||||
if(box == this)
|
||||
return _bounds == newRect ? false : (set_size(newRect), true);
|
||||
|
||||
for(size_t i = 0; i < _children.size(); ++i)
|
||||
{
|
||||
rect_t oldRect = _children[i]->bounds();
|
||||
if(_children[i]->resize(box, newRect))
|
||||
{
|
||||
rect_t newRect = _children[i]->bounds();
|
||||
if(_horizontal_layout)
|
||||
{
|
||||
if(oldRect.height() != newRect.height())
|
||||
{
|
||||
iterate(child, _children)
|
||||
{
|
||||
rect_t bounds = (*child)->bounds();
|
||||
bounds.y0 = newRect.y0;
|
||||
bounds.y1 = newRect.y1;
|
||||
(*child)->set_size(bounds);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(0 < i && oldRect.x0 != newRect.x0)
|
||||
{
|
||||
rect_t bounds = _children[i-1]->bounds();
|
||||
bounds.x1 = newRect.x0 - kViewSpacing;
|
||||
_children[i-1]->set_size(bounds);
|
||||
}
|
||||
|
||||
if(i+1 < _children.size() && oldRect.x1 != newRect.x1)
|
||||
{
|
||||
rect_t bounds = _children[i+1]->bounds();
|
||||
bounds.x0 = newRect.x1 + kViewSpacing;
|
||||
_children[i+1]->set_size(bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(oldRect.width() != newRect.width())
|
||||
{
|
||||
iterate(child, _children)
|
||||
{
|
||||
rect_t bounds = (*child)->bounds();
|
||||
bounds.x0 = newRect.x0;
|
||||
bounds.x1 = newRect.x1;
|
||||
(*child)->set_size(bounds);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(0 < i && oldRect.y0 != newRect.y0)
|
||||
{
|
||||
rect_t bounds = _children[i-1]->bounds();
|
||||
bounds.y1 = newRect.y0 - kViewSpacing;
|
||||
_children[i-1]->set_size(bounds);
|
||||
}
|
||||
|
||||
if(i+1 < _children.size() && oldRect.y1 != newRect.y1)
|
||||
{
|
||||
rect_t bounds = _children[i+1]->bounds();
|
||||
bounds.y0 = newRect.y1 + kViewSpacing;
|
||||
_children[i+1]->set_size(bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rect_t oldBounds = _bounds;
|
||||
_bounds = rect_t(INT_MAX, INT_MIN, INT_MAX, INT_MIN);
|
||||
iterate(child, _children)
|
||||
{
|
||||
_bounds.x0 = std::min(_bounds.x0, (*child)->x0());
|
||||
_bounds.x1 = std::max(_bounds.x1, (*child)->x1());
|
||||
_bounds.y0 = std::min(_bounds.y0, (*child)->y0());
|
||||
_bounds.y1 = std::max(_bounds.y1, (*child)->y1());
|
||||
}
|
||||
|
||||
return _bounds != oldBounds;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#ifndef BOX_H_LQ7DU4L2
|
||||
#define BOX_H_LQ7DU4L2
|
||||
|
||||
#include <oak/oak.h>
|
||||
#include <text/format.h>
|
||||
|
||||
struct rect_t
|
||||
{
|
||||
rect_t (int x0, int x1, int y0, int y1) : x0(x0), x1(x1), y0(y0), y1(y1) { }
|
||||
int width () const { return x1 - x0; }
|
||||
int height () const { return y1 - y0; }
|
||||
void set_width (int width) { x1 = x0 + width; }
|
||||
void set_height (int height) { y1 = y0 + height; }
|
||||
void move_to (int x, int y) { *this = rect_t(x, x + width(), y, y + height()); }
|
||||
bool contains (int x, int y) const { return oak::cap(x0, x, x1-1) == x && oak::cap(y0, y, y1-1) == y; }
|
||||
|
||||
bool operator== (rect_t const& rhs) const { return x0 == rhs.x0 && x1 == rhs.x1 && y0 == rhs.y0 && y1 == rhs.y1; }
|
||||
bool operator!= (rect_t const& rhs) const { return x0 != rhs.x0 || x1 != rhs.x1 || y0 != rhs.y0 || y1 != rhs.y1; }
|
||||
|
||||
int x0, x1, y0, y1;
|
||||
};
|
||||
|
||||
inline std::string to_s (rect_t const& r)
|
||||
{
|
||||
return text::format("%d, %d — %d × %d", r.x0, r.y0, r.width(), r.height());
|
||||
}
|
||||
|
||||
extern int kViewSpacing;
|
||||
|
||||
struct box_t
|
||||
{
|
||||
box_t (int width = 0, int height = 0, int minWidth = 0, int minHeight = 0, bool locked = false, bool horizontal = true);
|
||||
|
||||
int x0 () const { return _bounds.x0; }
|
||||
int y0 () const { return _bounds.y0; }
|
||||
int x1 () const { return _bounds.x1; }
|
||||
int y1 () const { return _bounds.y1; }
|
||||
int width () const { return _bounds.width(); }
|
||||
int height () const { return _bounds.height(); }
|
||||
void set_width (int aWidth) { set_size(rect_t(x0(), x0() + aWidth, y0(), y1())); }
|
||||
void set_height (int aHeight) { set_size(rect_t(x0(), x1(), y0(), y0() + aHeight)); }
|
||||
rect_t const& bounds () const { return _bounds; }
|
||||
|
||||
bool locked () const { return _locked; }
|
||||
void set_locked (bool flag) { _locked = flag; }
|
||||
bool horizontal () const { return _horizontal_layout; }
|
||||
std::vector<box_t*>& children () { return _children; }
|
||||
std::vector<box_t*> const& children () const { return _children; }
|
||||
|
||||
int min_width () const
|
||||
{
|
||||
int res = 0;
|
||||
iterate(child, _children)
|
||||
res = _horizontal_layout ? res + (*child)->min_width() : std::max(res, (*child)->min_width());
|
||||
return std::max(res, _min_width);
|
||||
}
|
||||
|
||||
int min_height () const
|
||||
{
|
||||
int res = 0;
|
||||
iterate(child, _children)
|
||||
res = !_horizontal_layout ? res + (*child)->min_height() : std::max(res, (*child)->min_height());
|
||||
return std::max(res, _min_height);
|
||||
}
|
||||
|
||||
void set_size (rect_t const& newBounds);
|
||||
bool resize (box_t* box, rect_t const& newRect);
|
||||
void freeze_layout ();
|
||||
box_t* find (int x, int y);
|
||||
void push_front (box_t* box);
|
||||
void push_back (box_t* box);
|
||||
box_t* erase (box_t* box);
|
||||
|
||||
private:
|
||||
rect_t _bounds;
|
||||
int _min_width, _min_height;
|
||||
int _ideal_width, _ideal_height;
|
||||
std::vector<box_t*> _children;
|
||||
bool _locked, _horizontal_layout;
|
||||
};
|
||||
|
||||
#endif /* end of include guard: BOX_H_LQ7DU4L2 */
|
||||
@@ -1,72 +0,0 @@
|
||||
#import <OakAppKit/OakLayoutView.h>
|
||||
|
||||
@interface MyLayoutView : OakLayoutView
|
||||
@end
|
||||
|
||||
@implementation MyLayoutView
|
||||
- (NSTextField*)createView:(NSString*)label
|
||||
{
|
||||
NSTextField* res = [[[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)] autorelease];
|
||||
[res setEditable:NO];
|
||||
[res setSelectable:NO];
|
||||
// [res setBezeled:NO];
|
||||
// [res setBordered:NO];
|
||||
// [res setDrawsBackground:NO];
|
||||
// [res setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[res setStringValue:label];
|
||||
return res;
|
||||
}
|
||||
|
||||
- (NSRectEdge)edgeOfView:(NSView*)aView containingPoint:(NSPoint)aPoint
|
||||
{
|
||||
NSSize size = [aView frame].size;
|
||||
NSRectEdge edge = NSMinYEdge;
|
||||
|
||||
if(aPoint.y < size.height/4)
|
||||
edge = NSMinYEdge;
|
||||
else if(aPoint.y > 3*size.height/4)
|
||||
edge = NSMaxYEdge;
|
||||
else if(aPoint.x < size.width/4)
|
||||
edge = NSMinXEdge;
|
||||
else if(aPoint.x > 3*size.width/4)
|
||||
edge = NSMaxXEdge;
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent*)anEvent
|
||||
{
|
||||
static NSInteger i = 0;
|
||||
NSPoint click = [anEvent locationInWindow];
|
||||
|
||||
NSUInteger flags = [anEvent modifierFlags];
|
||||
if(flags & NSShiftKeyMask)
|
||||
{
|
||||
NSView* newView = [self createView:[NSString stringWithFormat:@"View %ld", ++i]];
|
||||
NSRectEdge edge = [self edgeOfView:self containingPoint:[self convertPoint:click fromView:nil]];
|
||||
[self addView:newView atEdge:edge ofView:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
NSView* clickedView = [self hitTest:[[self superview] convertPoint:click fromView:nil]];
|
||||
if(clickedView)
|
||||
{
|
||||
NSView* newView = [self createView:[NSString stringWithFormat:@"View %ld", ++i]];
|
||||
NSRectEdge edge = [self edgeOfView:clickedView containingPoint:[clickedView convertPoint:click fromView:nil]];
|
||||
[self addView:newView atEdge:edge ofView:clickedView];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
class LayoutViewTests : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_layout_view ()
|
||||
{
|
||||
NSAutoreleasePool* pool = [NSAutoreleasePool new];
|
||||
MyLayoutView* layoutView = [[[MyLayoutView alloc] initWithFrame:NSMakeRect(0, 0, 400, 60)] autorelease];
|
||||
[layoutView addView:[layoutView createView:@"Root"]];
|
||||
OakSetupApplicationWithView(layoutView, "layout_view");
|
||||
[pool drain];
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user