Merge TextEditor: zoom and CPScrollView magnification
* AppKit: Add NSScrollView's magnification API to CPScrollView. A view
whose scale returns to 1.0 now drops its CSS scale. Scroll views from
cibs compiled by nib2cib can now zoom.
* TextEditor: View > Zoom Level, Zoom In, Zoom Out and Actual Size, from
25% to 200%, as a test of view scaling for the Aristo3 merge. The work
list records the scaling defects found as open.
CPScrollView previously lacked magnification support, preventing document
zooming and leaving view scaling infrastructure without practical test coverage.
Additionally, views resetting to a 1.0 scale retained stale CSS transform properties,
and legacy cibs compiled via nib2cib omitted explicit magnification limits,
breaking zoom functionality in older archives.
* AppKit/CPScrollView.j:
- Implement magnification methods and properties (`magnification`, `setMagnification:`, `setMagnification:centeredAtPoint:`, `allowsMagnification`, `minMagnification`, and `maxMagnification`) modelled on NSScrollView, with keyed archiving.
- Scale clip view bounds and synchronize resizing document view widths.
- Define standard Cocoa default limits (0.25 and 4.0) as named constants.
- Implement robust decoding validation to assign default limits to unset or invalid archive values and reject non-positive magnification inputs, ensuring full compatibility with legacy cibs.
* AppKit/CPView.j:
- Remove stale CSS scale styling when a view's scale factor returns to 1.0.
* Tests/AppKit/CPScrollViewTest.j:
- Add comprehensive unit tests covering magnification scaling, archiving, and fallback decoding for unconfigured limits.
* Tests/Manual/TextEditor/DocumentWindowController.j:
- Implement zoom action handlers (`zoomToLevel:`, `zoomToActualSize:`, `zoomIn:`, and `zoomOut:`) driven by menu item tag values.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, MainMenu.cib:
- Add View menu options for Actual Size, Zoom In, Zoom Out, and explicit Zoom Levels (25% to 200%).
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark zoom functionality as tested; log discovered scaling edge cases as open items.
CPScrollView and TextEditor now support robust document magnification from 25% to 200%, validating core view scaling mechanics.
Merge TextEditor fixes: attachments wider than the text
* AppKit: An attachment wider than the text container keeps its line's
height and baseline. A table in a narrowed window was drawn above its
line, over the preceding text.
When text attachments (such as tables or wide images) exceeded container width,
`CPTypesetter` correctly forced a line break following the attachment but
erroneously reverted the line's height and baseline to pre-attachment metrics.
Consequently, oversized attachments rendered on the baseline of preceding text,
causing them to overlap and obscure content above them in narrowed viewports.
* AppKit/CPTextView/CPTypesetter.j:
- Update line layout logic to incorporate attachment dimensions into line height
and baseline calculations when line breaks encompass overflowing attachments.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark wide/overflowing table layout tests as completed.
Attachments and tables wider than the text container now correctly occupy their own distinct lines without overlapping preceding content.
Merge TextEditor fixes: attachments move with their lines
* AppKit: When unchanged lines below an edit are kept and moved, their
attachment views and text spans now move on the screen at once. A
table pasted together with images was shown at the wrong position
until a scroll or resize.
When CPLayoutManager retained and repositioned unchanged line fragments
below an edit, `_CPLineFragment` incorrectly modified attachment view frames
directly and assigned an unused property to text spans. Consequently, moved
views remained visually stationary on screen because subsequent layout-pass
`setFrameOrigin:` calls detected matching origins, causing asynchronously loaded
elements (such as pasted tables combined with images) to render at incorrect
offsets until forced by a scroll or resize event.
* AppKit/CPTextView/CPLayoutManager.j:
- Update attachment view relocation to correctly trigger `setFrameOrigin:`.
- Shift rendered text spans via their style coordinate top properties.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark composite paste workflows (text containing both images and tables) as tested.
Attachment views and text spans now immediately track their corresponding line fragments when text is inserted or modified above them.
Merge TextEditor fixes: lists and Unicode in RTF, images in pasted text
* AppKit: The RTF producer and parser carry text lists, in Cocoa's form
and readable from Word's, Unicode characters, and the first line indent
relative to the left indent.
* AppKit: Copy and paste within an application keeps images, tables and
lists, through the internal archive. Tables can now be archived.
* TextEditor: The work list records that browsers deliver only plain
text to native applications, so rich text for them needs HTML.
The RTF producer and parser lacked support for text lists, failed to encode
non-ASCII characters properly (\uN), and treated first-line indents (\fi) as
absolute values rather than offsets relative to left indents (\li).
Additionally, paste operations ingested application-generated RTF rather than
the native internal archive, causing image attachments and tables to be stripped
during copy-paste workflows within the application.
* AppKit/CPTextView/_CPRTFProducer.j:
- Implement RTF serialization for text lists using list tables, override tables,
\levelmarker, \levelprepend, \lsN\ilvlK tags, and \listtext marker blocks.
- Encode non-ASCII characters via \uc0\uN syntax and compute \fi indents
relative to \li.
- Omit image attachment characters from text runs and adjust run starting indices
to accommodate list markers.
* AppKit/CPTextView/_CPRTFParser.j:
- Implement pre-pass parsing for list and override tables.
- Assign shared text lists to items using \ls and \ilvl, extracting marker formats
from \levelmarker or standard number/level definitions.
- Parse \uN sequences (skipping fallback characters) and evaluate relative \fi offsets.
* AppKit/CPTextView/CPTextView.j:
- Configure paste handling to prioritize internal archives when clipboard RTF
originates from the application, ensuring image attachments and tables survive internal copy-paste.
* AppKit/CPTextView/_CPTableTextAttachment.j:
- Implement keyed archiving and decoding for table headers, rows, widths,
and configuration settings, reconstructing cell instances upon unarchiving.
* Tests/AppKit/CPRTFTest.j:
- Add comprehensive unit tests covering Unicode encoding, relative first-line indents,
TextEdit and Word list interoperability, and nested list round-trip fidelity.
* Tests/AppKit/CPTextAttachmentTest.j:
- Add test coverage for table attachment archiving.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark intra-application copy and paste testing as completed.
- Log external rich text exchange limitations as open items.
Intra-application copy and paste now fully preserves images, tables, and lists,
while RTF serialization supports Unicode and structured hierarchical lists.
Merge TextEditor: table demonstration
* TextEditor: Edit > Insert Table Example inserts a sample document with
a table, built from Markdown by CPMarkdownParser. It demonstrates the
existing table support in a real document. The work list records the
remaining table checks and known gaps.
TextEditor lacked a mechanism to showcase or test CPMarkdownParser's
table rendering capabilities within a live document context.
* Tests/Manual/TextEditor/TableExample.j:
- Add a Markdown sample containing a heading, a formatted table with a header row and styled cells, and accompanying text, converted to an attributed string via CPMarkdownParser.
* Tests/Manual/TextEditor/DocumentWindowController.j:
- Implement insertTableExample: action to insert the table sample at the current selection.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, MainMenu.cib:
- Add Edit > Insert Table Example menu item.
* Tests/Manual/TextEditor/WORKLIST.md:
- Record table rendering as tested; log interactive validation and known table limitations as open items.
TextEditor now provides a live demonstration and testing baseline for rich text table layouts.
AppKit: Apply font changes without a selection to CPTextView typing attributes
When no text was selected, CPTextView's changeFont: implementation
erroneously extracted the font to convert from the text storage at the
insertion point rather than from current typing attributes. Consequently,
repeated adjustments like Bigger or Smaller failed to accumulate, blank
document font sizing remained locked after one step, and output arguments
risked overwriting selection state.
* AppKit/CPTextView/CPTextView.j:
- Update changeFont: to derive and convert fonts directly from typing
attributes when no selection is active, and post corresponding typing
attribute update notifications.
- Eliminate selection range output arguments that could inadvertently
modify active selection bounds.
* Tests/AppKit/CPTextViewTest.j:
- Add unit tests verifying that repeated font modifications accumulate correctly
at zero-length insertion points.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark Bigger and Smaller actions without a selection as tested.
Bigger and Smaller menu commands now correctly compound font size adjustments for subsequent typed text, matching Cocoa behavior.
When no text was selected, CPTextView's changeFont: implementation
erroneously extracted the font to convert from the text storage at the
insertion point rather than from current typing attributes. Consequently,
repeated adjustments like Bigger or Smaller failed to accumulate, blank
document font sizing remained locked after one step, and output arguments
risked overwriting selection state.
* AppKit/CPTextView/CPTextView.j:
- Update changeFont: to derive and convert fonts directly from typing
attributes when no selection is active, and post corresponding typing
attribute update notifications.
- Eliminate selection range output arguments that could inadvertently
modify active selection bounds.
* Tests/AppKit/CPTextViewTest.j:
- Add unit tests verifying that repeated font modifications accumulate correctly
at zero-length insertion points.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark Bigger and Smaller actions without a selection as tested.
Bigger and Smaller menu commands now correctly compound font size adjustments for subsequent typed text, matching Cocoa behavior.
Merge TextEditor fixes: images in text
* AppKit: Add CPTextAttachment, modelled on NSTextAttachment and drawn by
a view, as in TextKit 2. Images are inserted with Edit > Insert Image…
or pasted with Command-V, fit the width of the text, and scale with the
window. Existing view attachments, such as tables, are unchanged.
* AppKit: A resizable CPTextView fits its height to its last character,
so an image at the end of the text is not clipped.
* TextEditor: The work list records the untested image cases, file drops,
and image formats in RTF and Markdown as open.
Vertically resizable CPTextView instances previously calculated frame heights
using metrics from the first character, second-to-last character, and extra
line fragment, omitting the bounding box of the final character. Consequently,
trailing elements such as bottom-anchored image attachments were clipped,
and vertical scroll bars failed to match content bounds following scaling
or layout updates.
* AppKit/CPTextView/CPTextView.j:
- Include the final character's bounding rectangle when computing view height to fit text.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark wide image fitting tests as completed.
CPTextView containers now fully display trailing content and maintain accurate vertical scroll bar scaling.
AppKit lacked a public text attachment class, preventing rich text documents
from embedding or inserting images.
* AppKit/CPTextView/CPTextAttachment.j:
- Implement CPTextAttachment (modelled on NSTextAttachment) supporting
initialization via data and file type, contents, file types, images,
bounds, and keyed archiving.
- Adopt a TextKit 2-style view rendering architecture that scales images
to fit text container width and triggers layout updates upon asynchronous loading.
* AppKit/CPTextView/CPTextStorage.j:
- Update attributedStringWithAttachment: to accept CPTextAttachment instances
alongside direct views, routing rendering through existing attachment pathways.
* AppKit/CPTextView/CPTextView.j:
- Implement the insertImage: action (invoking browser file pickers) and
Command-V paste handling for images.
- Configure inserted attachments with responsive view instances scaled to
text width, omitting live views during pasteboard archiving.
* AppKit/CPTextView/CPTextContainer.j:
- Adjust attachment bounds to match updated container widths during layout invalidation.
* AppKit/AppKit.j:
- Export CPTextAttachment.
* Tests/AppKit/CPTextAttachmentTest.j:
- Add test coverage for data URLs, archiving, width scaling, insertion,
and serialized text output.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, MainMenu.cib:
- Add Edit > Insert Image… menu item.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark image insertion testing as completed; log remaining image tasks as open.
Rich text documents now support embedded images inserted via file selection or clipboard paste.
AppKit: Integrate Edit menu clipboard actions with the system clipboard
CPTextView previously relied solely on browser clipboard events triggered by
keyboard equivalents, isolating Edit menu actions (Copy, Paste) to an internal
pasteboard. Consequently, menu operations ignored external system clipboard
modifications, and Command-V could mistakenly paste stale internal rich text
following an external copy operation.
* AppKit/CPTextView/CPTextView.j:
- Distinguish menu- and button-driven clipboard actions from browser keyboard event handlers.
- Implement asynchronous Clipboard API integration to write plain text to the system clipboard on copy/cut and read external content for Paste and Paste as Plain Text.
- Implement intelligent clipboard reconciliation: preserve internal rich text if the system clipboard plain text matches, or ingest external system clipboard text (including for Command-V shortcuts).
- Ensure Cut operates correctly across all input vectors.
* Tests/AppKit/CPTextViewTest.j:
- Add unit tests verifying text ingestion and pasting from the system clipboard.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark Edit menu clipboard synchronization as tested.
- Log rich-text serialization over the asynchronous Clipboard API as an opportunity for future improvement.
Copy, Cut, and Paste operations from the Edit menu now seamlessly exchange plain text with external applications.
CPTextView previously relied solely on browser clipboard events triggered by
keyboard equivalents, isolating Edit menu actions (Copy, Paste) to an internal
pasteboard. Consequently, menu operations ignored external system clipboard
modifications, and Command-V could mistakenly paste stale internal rich text
following an external copy operation.
* AppKit/CPTextView/CPTextView.j:
- Distinguish menu- and button-driven clipboard actions from browser keyboard event handlers.
- Implement asynchronous Clipboard API integration to write plain text to the system clipboard on copy/cut and read external content for Paste and Paste as Plain Text.
- Implement intelligent clipboard reconciliation: preserve internal rich text if the system clipboard plain text matches, or ingest external system clipboard text (including for Command-V shortcuts).
- Ensure Cut operates correctly across all input vectors.
* Tests/AppKit/CPTextViewTest.j:
- Add unit tests verifying text ingestion and pasting from the system clipboard.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark Edit menu clipboard synchronization as tested.
- Log rich-text serialization over the asynchronous Clipboard API as an opportunity for future improvement.
Copy, Cut, and Paste operations from the Edit menu now seamlessly exchange plain text with external applications.
Merge TextEditor fixes: text lists
* AppKit: Add CPTextList and textLists in CPParagraphStyle, modelled on
Cocoa. CPTextView supports bulleted, numbered and nested lists, with
Cocoa's editing behaviour for Return, Tab, Shift-Tab and Delete, and
numbering that follows each change. Paste Ruler carries lists.
* AppKit: Typing attributes and the font panel take the style of the
character before the insertion point, as in Cocoa.
* AppKit: Shift-Tab reaches a text view that takes the Tab key, and is
bound to insertBacktab:.
* TextEditor: Format > List applies list styles. The work list records
RTF support for lists as open.
AppKit lacked CPTextList and the textLists property on CPParagraphStyle,
preventing rich text from supporting bulleted or numbered lists. Additionally,
CPTextView derived its typing attributes from the character following the
insertion point upon selection changes, causing text appended at the end of a
document (and the Font Panel) to incorrectly revert to default styling.
* AppKit/CPTextView/CPTextList.j:
- Implement CPTextList following NSTextList specifications, including standard
Cocoa marker formats, CPTextListPrependEnclosingMarker, starting item numbers,
markerForItemNumber:, isOrdered, and keyed archiving.
- Add rangeOfTextList:atIndex: and itemNumberInTextList:atIndex: category
extensions to CPAttributedString.
* AppKit/CPTextView/CPParagraphStyle.j:
- Add textLists and setTextLists: properties with copy and archiving support.
- Implement paragraph style equality checks based on list identity.
* AppKit/CPTextView/CPTextView.j:
- Implement setTextList: and the changeTextList: action method (routing marker
styles via sender tags). Adjacent paragraphs with matching styles join automatically.
- Implement list item keyboard navigation and editing mechanics: Return generates
subsequent list items, Return on an empty item terminates list context,
Tab at item origin nests levels, Shift-Tab promotes levels, and Delete at item
text origin strips list membership.
- Automate list item renumbering during live edits, paste operations, and undo/redo cycles.
- Update Paste Ruler routines to correctly synthesize, strip, and merge list markers.
- Fix typingAttributes and Font Panel attribute resolution to derive from the
first selected character or the character immediately preceding the insertion point.
* AppKit/CPKeyBinding.j:
- Bind Shift-Tab selector to insertBacktab:.
* AppKit/CPWindow/CPWindow.j:
- Update key event routing to dispatch Shift-Tab to first responders that accept Tab.
* AppKit/AppKit.j:
- Export CPTextList.
* Tests/AppKit/CPTextListTest.j:
- Add unit test coverage for marker formatting, archiving, list range queries,
interactive list editing, Paste Ruler execution, and menu action validation.
* Tests/AppKit/CPTextViewTest.j:
- Add test coverage verifying typing attributes at trailing insertion points.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, MainMenu.cib:
- Add Format > List menu structures containing bulleted, numbered, and outline choices.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark list interaction testing as completed; log RTF list serialization as an open item.
CPTextView now provides Cocoa-compliant bulleted, numbered, and nested list support.
Merge TextEditor fixes: Copy Style and Paste Style
* AppKit: CPTextView implements Cocoa's copyFont: and pasteFont:, with
undo and menu validation. Choosing Copy Style or Paste Style no longer
raises an exception and leaves the menu unresponsive.
* TextEditor: The work list records Copy Style and Paste Style as tested.
CPTextView lacked implementations for copyFont: and pasteFont:
(declared as abstract methods in CPText), causing standard Copy Style and Paste Style menu items to trigger exceptions when invoked.
* AppKit/CPTextView/CPTextView.j:
- Implement copyFont: to copy character attributes (excluding paragraph style, matching Cocoa) of the initial selection character or current typing attributes to the font pasteboard.
- Implement pasteFont: to apply copied character attributes to the selection or typing attributes with undo support, preserving individual paragraph styles.
- Update menu validation logic to enable Copy Style in rich text and Paste Style in editable rich text when the font pasteboard contains valid styling.
* Tests/AppKit/CPTextViewTest.j:
- Add unit tests covering style copying and pasting with and without active selections.
- Add test coverage for menu validation.
* Tests/Manual/TextEditor/WORKLIST.md:
- Record Copy Style and Paste Style as tested.
Copy Style and Paste Style now function consistently with Cocoa.
Merge TextEditor fixes: justified text alignment
* AppKit: CPTypesetter justifies wrapped lines and aligns centred,
right-aligned and justified text between the paragraph indents.
Spaces at the end of a wrapped line hang outside the alignment.
* TextEditor: The work list records the limited quality of greedy line
breaking for justified text as an opportunity for improvement.
CPTypesetter lacked handling for CPJustifiedTextAlignment, causing justified paragraphs to fall back to left alignment. Additionally, centred and right-aligned text improperly spanned the full container width by ignoring paragraph indents, and trailing spaces on wrapped lines incorrectly shifted line positioning.
* AppKit/CPTextView/CPTypesetter.j:
- Implement CPJustifiedTextAlignment layout by distributing spare width evenly across line spaces.
- Preserve left alignment for paragraph final lines and segments preceding a tab, matching Cocoa behavior.
- Constrain centred, right-aligned, and justified lines between head and tail indents.
- Exclude trailing spaces from visible line width to allow proper hanging alignment.
* AppKit/CPTextView/CPLayoutManager.j:
- Update _CPLineFragment to record extra space widths and render spans with matching CSS word-spacing.
- Ensure fragment equality checks account for word-spacing variations.
* Tests/Manual/TextEditor/WORKLIST.md:
- Mark justified and centred text layout tests as completed.
Centred and justified paragraphs now conform to standard Cocoa layout behavior.
Merge TextEditor fixes: superscript, subscript and baseline management
* AppKit: CPTextView implements Cocoa's superscript:, subscript:, unscript:,
raiseBaseline: and lowerBaseline: actions, with undo and menu validation.
* TextEditor: The work list documents text layout and records the Justify
crash, kerning and ligature settings, and font panel as open items.
CPTextView lacked the superscript:, subscript:, unscript:, raiseBaseline:, and lowerBaseline: action methods.
Consequently, standard Baseline menu items targeting these actions were automatically disabled,
even though CPTypesetter and _CPLineFragment already possessed full layout support for baseline offset and superscript attributes.
* AppKit/CPTextView/CPTextView.j:
- Implement superscript:, subscript:, unscript:, raiseBaseline:, and lowerBaseline:.
- Apply attribute modifications to selected ranges or current typingAttributes.
- Register baseline operations with CPUndoManager.
- Implement menu validation logic to enable baseline actions only when the text view is editable and richText is true.
* Tests/AppKit/CPTextViewTest.j:
- Add unit tests for superscript levels and baseline offsets across text ranges and typing attributes.
- Add test coverage for menu validation.
* Tests/Manual/TextEditor/WORKLIST.md:
- Remove resolved baseline management entry.
- Expand documentation on text layout and line fragment drawing.
- Document open items: Justify crash, kerning/ligature settings, and Font Panel integration.
- Note optimal line breaking as a candidate feature for future improvement.
Merge TextEditor fixes: ruler settings from Interface Builder, Copy and Paste Ruler
Gaps exposed by the TextEditor test application:
* AppKit, nib2cib: A text view's Uses Ruler setting now comes from Interface Builder, and text views, rulers and ruler markers archive their ruler state.
* AppKit: A dragged ruler marker follows the pointer off the ruler and is removed when released there.
* AppKit: Copy Ruler and Paste Ruler copy a paragraph's indents and tab stops to other paragraphs, and ruler changes can be undone.
CPTextView had no copyRuler: or pasteRuler:, so Format > Text > Copy Ruler and Paste Ruler did nothing, and ruler changes could not be undone. It now follows Cocoa: Copy Ruler puts the paragraph style at the selection on the ruler pasteboard, Paste Ruler applies it to the selected paragraphs, and every ruler change is registered with the undo manager.
* CPPasteboard.j: Add CPRulerPboardType.
* CPTextView/CPTextView.j: Add copyRuler: and pasteRuler: with validation for rich text; register ruler paragraph style changes with the undo manager; refresh the ruler after a replacement.
* Tests/Manual/TextEditor/WORKLIST.md: Record Copy Ruler and Paste Ruler as tested, and add the Copy Style and Paste Style exception.
nib2cib ignored the text view's Uses Ruler setting, and CPTextView, CPRulerView and CPRulerMarker archived none of their ruler state, so a ruler could not be configured in Interface Builder or survive archiving.
* CPScrollView.j: Set itself as the scroll view of decoded rulers.
* CPTextView/CPRulerMarker.j: Archive the marker's ruler, location, image and image origin, movability, removability and represented object.
* CPTextView/CPRulerView.j: Archive the ruler's orientation, client view, accessory view, markers, thicknesses, origin offset and measurement units.
* CPTextView/CPTextView.j: Archive usesRuler.
* Tools/nib2cib/NSTextView.j, Tools/nib2cib/NSTextViewSharedData.j: Read the Uses Ruler flag.
* Tests/AppKit/CPRulerViewTest.j: Add tests for ruler layout, measurement units, archiving and the Uses Ruler setting.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, Resources/MainMenu.cib: Add the standard Format menu, whose Text submenu shows and hides the ruler.
* Tests/Manual/TextEditor/Resources/DocumentWindow.xib, Resources/DocumentWindow.cib: Rebuild the cib with the ruler setting, and adjust the window's initial position.
Gaps exposed by the TextEditor test application and fixed:
* AppKit: CPRulerView and CPRulerMarker now follow NSRulerView and NSRulerMarker, and CPTextView gains Cocoa's ruler control methods, a right indent marker and ruler updates on every selection change.
* AppKit: An editable text view now receives the Tab key, and decimal tab stops align on the decimal separator.
* AppKit: Text layout applies Cocoa's line fragment padding, and a tracking text container fits inside the text view's inset.
A removable marker counted as off the ruler only 16 points beyond its edge, and stayed on its line while dragged off, so a tab stop dragged up off the ruler gave no sign of removal and was not removed on release.
It now follows Cocoa behaviour: the marker stays on its line while the pointer is on the ruler, follows the pointer out over the ruler's outer edge where the ruler clips it, and is removed when released off the ruler.
* CPTextView/CPRulerMarker.j: Reduce the removal distance from 16 points to zero; offset the marker across the ruler as the pointer moves outward during a drag, and draw it faded only when dragged off the inner edge.
* Tests/Manual/TextEditor/WORKLIST.md: Record the marker appearance and vertical alignment as interim until Aristo3, and the drag behaviour in each direction.
The typesetter laid a decimal tab stop out like a left tab, so a column of numbers started at the stop instead of aligning on its decimal separators. It now follows Cocoa: the first decimal separator of the user's locale starts at the stop, and a segment without one ends at the stop.
* CPTextView/CPTypesetter.j: Position text after a decimal tab stop by the width before its first decimal separator, taken from the browser's locale.
* Tests/Manual/TextEditor/WORKLIST.md: Record the Tab key and the four tab stop types as tested, and the tab stop menu as working.
CPWindow handled every Tab key press itself and moved to the next key view, so a text view never received Tab and could not insert a tab character.
It now follows Cocoa: an editable text view takes plain Tab and inserts a tab, while Control-Tab, Shift-Tab and Tab in other views still move through the key view loop.
* CPResponder.j: Add _wantsTabKey, which returns NO by default.
* CPTextView/CPTextView.j: Want the Tab key while editable.
* CPWindow/CPWindow.j: Pass plain Tab to a first responder that wants it, and keep the browser from moving its own focus.
The new ruler drew tab stops as L-shaped brackets, which differed from the triangles earlier versions showed, and placed marker images at fractional positions, so identical markers drew differently along the ruler.
* CPTextView/CPRulerMarker.j: Round marker image positions to whole points.
* CPTextView/CPTextView.j: Draw tab stops as triangles pointing right for a left tab, left for a right tab and down for a centre or decimal tab, with whole-point image origins.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the ruler and text layout entries fixed in this series, move the remaining nib2cib ruler entry to the nib2cib section, and record the ruler and text width as tested.
CPTextContainer's line fragment padding was 0 and the typesetter never applied it, so text started 2 points from the text view's edge and ruler markers at 0 were cut off. It now follows Cocoa, with a default padding of 5 points at each end of every line fragment.
* CPTextView/CPTextContainer.j: Default the line fragment padding to 5 points, and archive it.
* CPTextView/CPTypesetter.j: Lay lines out inside the padding: offset line fragment origins by it, compute the right margin, right indent, centred and right alignment within the width inside it, and subtract it when layout resumes from a stored line fragment.
* CPTextView/CPTextView.j: Start the caret in empty text inside the padding.
A text container that tracked its text view's size took the text view's full width, while the text started after the text container inset, so lines could run past the visible right edge.
It now follows Cocoa: a tracking container fills the text view minus the inset on both sides.
* CPTextView/CPTextContainer.j: Subtract the text container inset on both sides when tracking the text view's width and height.
* CPTextView/CPTextView.j: Refit the text container when a text view is created and when its text container inset changes.
Ruler classes departed from canonical NS versions, resulting in functional and visual gaps.:
markers were views that drew text characters and ignored their location argument, the ruler rebuilt its subviews on every update and had no origin offset, measurement units or reserved thicknesses, and CPTextView updated the ruler only on focus and typing attribute changes, had no ruler control methods, and never showed a right indent marker.
* AppKit.j: Import CPRulerMarker and CPRulerView.
* CPScrollView.j: Tile rulers by their required thickness, and give a ruler its scroll view when it is set.
* CPTextView/CPRulerMarker.j: Add CPRulerMarker as an object drawn by its ruler, with a marker location, an image and image origin, movability and removability, and tracking that adds, moves and removes markers through the client view.
* CPTextView/CPRulerView.j: Rewrite CPRulerView with an origin offset, registered measurement units defaulting to the user's region, reserved thicknesses for markers and an accessory view, Cocoa's client view methods, temporary ruler lines, and drawing in a single pass.
* CPTextView/CPTextView.j: Add usesRuler, isRulerVisible, setRulerVisible: and toggleRuler: with a Show Ruler or Hide Ruler title; update the ruler on every selection change; place tab stop, first line, head and tail indent markers relative to the start of the text, with SVG marker images and a context menu for changing tab types and resetting indents.
* Tests/Manual/TextEditor/DocumentWindowController.j: Show the ruler through setRulerVisible:.
A text view handled undo: and redo: and registered its changes even when allowsUndo was NO, so Edit > Undo stayed enabled and did nothing.
Behaviour now follows canonical Cocoa: a text view that does not allow undo registers nothing and passes undo: and redo: on to the window, and Undo and Redo are enabled only when there is a change to undo or redo.
* CPTextView/CPTextView.j: Register changes only when undo is allowed, stop responding to undo: and redo: when it is not, and validate the Undo and Redo items against the undo manager.
* CPWindow/CPWindow.j: Validate the Undo and Redo items against the window's undo manager.
* Tests/AppKit/CPTextViewTest.j: Add tests for responding to undo:, registering changes and validating the Undo item.
* Tests/Manual/TextEditor/DocumentWindowController.j: Add toggleAllowsUndo: and validateMenuItem:, so that undo can be turned on and off for the active document.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, Resources/MainMenu.cib: Add Edit > Allow Undo.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this gap, record Allow Undo as tested, and add the key equivalent behaviour of disabled menu items for discussion.
AppKit read only CPBundleName for the name that users see, so an application's display name was ignored. It now follows Cocoa, which shows CFBundleDisplayName and falls back to CFBundleName.
* CPApplication.j: Add _applicationName, which returns CPBundleDisplayName or, without one, CPBundleName, and use it as the About panel title.
* CPMenu/_CPMenuBarWindow.j: Use the display name in the browser tab title.
* Tests/Manual/TextEditor/Info.plist: Rename the display name key from CFBundleDisplayName to CPBundleDisplayName.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this gap, and record the About panel as tested.
Gaps exposed by the TextEditor test application and fixed in AppKit, Foundation:
* Foundation: CPUndoManager no longer raises when undo runs in the same run loop cycle as the change it reverts.
* AppKit: The Show Toolbar menu item now reflects the toolbar's visibility.
* AppKit: The Window menu now lists the application's windows, marks the main window and supports Bring All to Front.
The Window menu never listed the application's windows, because AppKit had none of Cocoa's Windows menu support.
* CPApplication.j: Add windowsMenu, setWindowsMenu:, addWindowsItem:title:filename:, changeWindowsItem:title:filename:, removeWindowsItem:, updateWindowsItem: and arrangeInFront:; find the menu named _CPWindowsMenu in the main menu, and list the visible windows when the main menu is set.
* CPWindow/CPWindow.j: Add isExcludedFromWindowsMenu and setExcludedFromWindowsMenu:, and keep the window's item current when the window is ordered in or out, retitled, made main or no longer main, miniaturized, deminiaturized or closed.
* Tests/AppKit/CPApplicationWindowsMenuTest.j: Add tests for listing, retitling, exclusion, the main window check mark, separator handling, file name titles and moving items to another Windows menu.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this gap, and record the Window menu as tested.
The Show Toolbar menu item toggled the toolbar, but CPWindow did not validate it, so its title never changed and it stayed enabled in windows without a toolbar.
* CPWindow/CPWindow.j: Add validateUserInterfaceItem:, which sets the toggleToolbarShown: item's title to Hide Toolbar or Show Toolbar and enables it only when the window has a toolbar.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this defect, and record the menu item as tested.
The TextEditor work list recorded redo as unreliable. Retesting proved that undo and redo work correctly.
Supporting investigation disclosed an edge case in CPUndoManager: when undo ran in the same run loop cycle as the change it reverted, it closed the open event grouping itself, but the run loop's scheduled close still ran and raised CPInternalInconsistencyException because no grouping was open.
* Foundation/CPUndoManager.j: Cancel the run loop's scheduled close when undo closes the event grouping itself.
* Tests/Foundation/CPUndoManagerTest.j: Add a test that undoes a change in the same run loop cycle and then redoes it, and correct the doIt selector registered by the undoIt helper.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the redo entry recorded in error, and record undo and redo as tested.
A window stored the proposed size in its frame before asking its delegate through windowWillResize:toSize:, and gave the delegate's size only to the window view. When the delegate enlarged the size, hit testing used the smaller frame, so the window could no longer be moved or resized.
* CPWindow/CPWindow.j: Ask the delegate before storing the new size, and store the size it returns in the frame.
* CPWindow/_CPWindowView.j: Ask the delegate during a user resize, and move the origin by the delegate's adjustment when resizing from the left or top edge, so that the opposite edge stays in place.
* Tests/Manual/TextEditor/Resources/DocumentWindow.xib: Make the document window's content view resize with the window.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this defect, record the minimum window size behaviour as tested, and add the content view resizing setting that does not reach the cib.
Add the AppKit gaps found since the work list was created, and describe the visible effect of the window resize defect.
* WORKLIST.md: Add entries for CPBundleDisplayName, which AppKit ignores, and for the Show Toolbar menu item, which never reflects the toolbar state; state that a window shrunk to its minimum size can no longer be moved or resized, because hit testing uses the unclamped frame.
Give TextEditor a display name and a real bundle identifier, and replace the template copyright and author placeholders.
* Info.plist: Set the bundle identifier to dev.cappuccino.TextEditor, add the display name TextEdit by Cappuccino, and state the MIT license in the copyright string.
* Jakefile: Set the same bundle identifier and remove the placeholder email.
* Resources/MainMenu.xib, Resources/MainMenu.cib: Use the display name in the application menu, About and Help items.