mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-27 14:07:03 +00:00
new: constrain tab stop marker movement between preceding text and adjacent tab stops
This commit is contained in:
@@ -2754,12 +2754,22 @@ var compareTabStops = function(obj1, obj2, context) {
|
||||
|
||||
var theString = [_textStorage string],
|
||||
minLocation = 0.0,
|
||||
containerWidth = [_textContainer containerSize].width,
|
||||
maxLocation = containerWidth,
|
||||
currentParagraphStyle = [_textStorage attribute:CPParagraphStyleAttributeName atIndex:targetRange.location effectiveRange:nil] || [CPParagraphStyle defaultParagraphStyle],
|
||||
tabStops = [currentParagraphStyle tabStops] || [];
|
||||
tabStops = [currentParagraphStyle tabStops] || [],
|
||||
tabCount = [tabStops count];
|
||||
|
||||
// Find which tab stop index this marker represents
|
||||
// 1. Right boundary: Tail indent (if configured)
|
||||
var tailIndent = [currentParagraphStyle tailIndent];
|
||||
if (tailIndent > 0.0)
|
||||
maxLocation = Math.min(maxLocation, tailIndent);
|
||||
else if (tailIndent < 0.0)
|
||||
maxLocation = Math.min(maxLocation, containerWidth + tailIndent);
|
||||
|
||||
// 2. Identify active tab stop index
|
||||
var targetTabIndex = -1;
|
||||
for (var i = 0; i < [tabStops count]; i++)
|
||||
for (var i = 0; i < tabCount; i++)
|
||||
{
|
||||
var tab = [tabStops objectAtIndex:i];
|
||||
if (tab === rep || ([tab location] === [rep location] && [tab alignment] === [rep alignment]))
|
||||
@@ -2769,6 +2779,39 @@ var compareTabStops = function(obj1, obj2, context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Constrain to neighboring tab stops (Left and Right)
|
||||
var safetySpacer = 2.0;
|
||||
|
||||
if (targetTabIndex !== -1)
|
||||
{
|
||||
// Left neighbor constraint (previous tab stop)
|
||||
if (targetTabIndex > 0)
|
||||
{
|
||||
var prevTab = [tabStops objectAtIndex:targetTabIndex - 1];
|
||||
minLocation = Math.max(minLocation, [prevTab location] + safetySpacer);
|
||||
}
|
||||
|
||||
// Right neighbor constraint (next tab stop)
|
||||
if (targetTabIndex + 1 < tabCount)
|
||||
{
|
||||
var nextTab = [tabStops objectAtIndex:targetTabIndex + 1];
|
||||
maxLocation = Math.min(maxLocation, [nextTab location] - safetySpacer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For new markers being added between existing tab stops
|
||||
for (var i = 0; i < tabCount; i++)
|
||||
{
|
||||
var tabLoc = [[tabStops objectAtIndex:i] location];
|
||||
if (tabLoc < proposedLocation)
|
||||
minLocation = Math.max(minLocation, tabLoc + safetySpacer);
|
||||
else if (tabLoc > proposedLocation)
|
||||
maxLocation = Math.min(maxLocation, tabLoc - safetySpacer);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Constrain to preceding text on active lines
|
||||
var start = targetRange.location,
|
||||
end = CPMaxRange(targetRange),
|
||||
tabCountInLine = 0,
|
||||
@@ -2786,7 +2829,6 @@ var compareTabStops = function(obj1, obj2, context) {
|
||||
|
||||
if (charCode === 9) // '\t'
|
||||
{
|
||||
// If this tab corresponds to the marker being dragged
|
||||
if (tabCountInLine === targetTabIndex || targetTabIndex === -1)
|
||||
{
|
||||
var precedingX = 0.0;
|
||||
@@ -2797,21 +2839,23 @@ var compareTabStops = function(obj1, obj2, context) {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find right edge of glyph immediately preceding the tab
|
||||
var glyphRect = [_layoutManager boundingRectForGlyphRange:CPMakeRange(i - 1, 1) inTextContainer:_textContainer];
|
||||
precedingX = CGRectGetMaxX(glyphRect);
|
||||
}
|
||||
|
||||
// Minimum safety spacer (e.g. + 2px after the preceding glyph)
|
||||
var limit = precedingX + 2.0;
|
||||
if (limit > minLocation)
|
||||
minLocation = limit;
|
||||
var textLimit = precedingX + safetySpacer;
|
||||
if (textLimit > minLocation)
|
||||
minLocation = textLimit;
|
||||
}
|
||||
tabCountInLine++;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.max(minLocation, proposedLocation);
|
||||
if (minLocation > maxLocation)
|
||||
minLocation = maxLocation;
|
||||
|
||||
// 5. Clamp proposedLocation within [minLocation, maxLocation]
|
||||
return Math.min(maxLocation, Math.max(minLocation, proposedLocation));
|
||||
}
|
||||
|
||||
- (float)rulerView:(CPRulerView)aRulerView willAddMarker:(CPRulerMarker)aMarker atLocation:(float)proposedLocation
|
||||
|
||||
Reference in New Issue
Block a user