Files
cappuccino/Tests/Manual/TextEditor/WORKLIST.md
T
David Richardson 66ea130c8d AppKit: Disable Undo and Redo when a text view does not allow undo
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.
2026-10-23 17:20:27 -06:00

75 lines
6.5 KiB
Markdown

# TextEditor Work List
TextEditor is a document-based test application and a tutorial. When the app uses AppKit, it shows gaps in the framework. This list records those gaps and the planned additions to the app.
## AppKit gaps
### Windows and documents
- **The "save changes" alert is modal for the whole app.** `CPDocument` shows it with `runModal` (`CPDocument.j:903`). Cocoa attaches it as a sheet to the document window, so that only that document is blocked.
- **Save cannot work without a server.** With no file URL, Save uses `CPSavePanel`, which falls back to `window.prompt` (`CPSavePanel.j:79`). `CPDocument` then sends an HTTP POST. A storage facade is needed, with local (IndexedDB) and remote (HTTP) implementations.
### Text view and ruler
- **The ruler markers do not update at the right times.** `CPTextView` calls `updateRuler` only when it becomes first responder (`CPTextView.j:547`) and when its typing attributes change (`:1819`). It must also update the ruler when the selection changes and when the ruler is first shown.
- **Indent markers at location 0 are half hidden.** `_positionMarker:` centres each marker on its location, so a marker at 0 starts at x = -6 (`CPRulerView.j`).
- **The ruler scale is offset from the text.** The text starts at the text container inset (2 points). The ruler has no origin offset for it.
- **Text runs past the right edge.** When the text view resizes, the text container takes the full width of the text view and ignores the inset (`CPTextContainer.j:199`).
- **There is no right indent.** `CPParagraphStyle` stores `tailIndent`, and `CPTextView` handles a moved `CPTailIndent` marker (`CPTextView.j:2630`). But `updateRuler` never creates that marker, and the typesetter ignores `tailIndent`.
- **nib2cib ignores the ruler settings.** The "Uses Ruler" setting in Interface Builder does not reach the cib.
- **`CPTextView` has no ruler control API.** `usesRuler`, `setUsesRuler:`, `setRulerVisible:` and `toggleRuler:` do not exist. `isRulerVisible` always returns `NO` (`CPTextView.j:2088`).
- **`CPRulerMarker` ignores `markerLocation`.** `initWithRulerView:markerLocation:imageValue:representedObject:` uses `imageValue` as the location.
### Clipboard
- **Paste and Cut from the Edit menu do nothing.** `-[CPTextView paste:]` (`CPTextView.j:521`) and `cut:` (`:1754`) return unless the current event is `CPAppKitDefined`. Only the browser's native clipboard events, from the keyboard, create that event.
- **Copy from the Edit menu cannot reach the system clipboard.** It fills only the internal `CPPasteboard`.
- **Fix:** when a menu item calls these methods, use the asynchronous Clipboard API (`navigator.clipboard`). Read RTF first, then plain text. Write plain text, and RTF where the browser allows it. Keep the keyboard path unchanged.
### Toolbar
- **The Fonts and Print standard items are not implemented.** `_standardItemWithItemIdentifier:` returns `nil` for both (`_CPToolbarItem.j:641`). AppKit needs `_CPToolbarShowFontsItem` (sends `orderFrontFontPanel:`) and `_CPToolbarPrintItem` (sends `printDocument:`). nib2cib needs matching classes.
### Text features not yet supported
- **Images in text.** AppKit has no general `CPTextAttachment` class, only the table attachment `_CPTableTextAttachment`. The RTF parser and producer do not handle `\pict`.
- **Lists.** There is no `CPTextList`, and `CPParagraphStyle` has no `textLists`.
### nib2cib
- **The content view's resizing setting does not reach the cib.** Making the document window's content view resize with the window in `DocumentWindow.xib` produces a byte-identical `DocumentWindow.cib`. CPView omits the autoresizing mask from the archive only when it is `CPViewNotSizable` (`CPView.j:4016`), so the content view is archived as not sizable. Not yet determined whether `ibtool` or nib2cib drops the setting. The app still behaves correctly, because the window resizes its content view itself.
### Menus and key equivalents (needs discussion)
- **The key equivalent of a disabled menu item reaches the browser.** `-[CPMenu performKeyEquivalent:]` (`CPMenu.j:1059`) stops the browser's default action only when the matching item is enabled. For a disabled item it reports the key as handled, but the browser still acts on it: with File > Close disabled, Cmd-W closes the browser tab. Cocoa consumes the key equivalent of a disabled item with a beep. Stopping the browser's default for disabled items as well would match Cocoa for most keys, but not all: some browsers do not let a page block certain shortcuts, such as Cmd-W, Cmd-N and Cmd-T in Chrome, and Copy, Cut and Paste must keep reaching the browser for its clipboard events. This needs careful thought, and perhaps discussion, before any change.
### Platform
- **Key equivalents on platforms other than macOS.** Filed as an issue.
## Planned additions to the app
- Fonts through `CPFontManager` and `CPFontPanel`.
- RTF reading and writing.
- Images and lists in text.
- A storage facade, with saving and opening in IndexedDB and through HTTP.
- An asynchronous fetch test: fetch the text of a page and show it for editing. The page must allow cross-origin requests.
- An inspector pane with `CPSplitViewController` and `CPViewController`, with a View menu item that sends `toggleInspector:`.
- Documents in separate browser windows with `CPPlatformWindow`.
- A Settings window. The first setting is the minimum size of document windows, now the constants `DocumentWindowMinimumWidth` and `DocumentWindowMinimumHeight` in `DocumentWindowController.j`.
## Tests done
- One window for each document, each loaded from its own cib.
- Insert Lorem Ipsum through the responder chain.
- Undo and redo over several levels, separate for each document.
- Text colour through `CPColorPanel`.
- Paragraph indents through the ruler markers.
- The "save changes" alert when a document closes.
- A minimum size for document windows, through the window delegate. The window stops at the minimum while the pointer keeps moving, as in macOS, and it can still be moved and resized afterwards.
- View > Show Toolbar and Hide Toolbar: the item's title follows the toolbar's visibility.
- The Window menu lists the open document windows, marks the main window with a check mark and brings a window to the front when chosen. Bring All to Front can be tested once documents open in separate browser windows.
- The About panel shows the display name from `CPBundleDisplayName`.
- Edit > Allow Undo turns undo on and off for the active document. With undo off, Undo and Redo stay disabled, and the check mark follows the document in front.
- Builds with both the legacy toolchain and capp-build.