|
|
Line 1: |
Line 1: |
− | TMemo widgetset is implemented over NSTextView and NSScrollView
| + | #REDIRECT [[Cocoa Internals/Text Controls]] |
− | | |
− | ==NSTextView==
| |
− | By default NSTextView is designed to be constantly word-wrapped. Disabling word-wrapping could be quite complicated from a start due to odd-default values chosen by Apple, as well as complex (yet flexible) Text Layout system.
| |
− | * NSTextView is a "cocoa" control, however it's not drawing the text by it's own it's also using:
| |
− | * NSTextContainer. Both NSTextContainer and NSTextView settings influence on how the text is rendered in the end.
| |
− | | |
− | The example shows, of creating NSTextView that automatically resizes itself horizontally.
| |
− | However NSTextView doesn't provide its own scrollbars, thus no scrollbars would be seen.
| |
− | <source lang="delphi">
| |
− | procedure TForm1.FormShow(Sender: TObject);
| |
− | var
| |
− | txt : NSTextView;
| |
− | begin
| |
− | txt := NSTextView.alloc.initWithFrame(NSMakeRect(10,ClientHeight-10-50,50,50));
| |
− | | |
− | txt.setFont(NSFont.systemFontOfSize(NSFont.systemFontSizeForControlSize(NSRegularControlSize)));
| |
− | | |
− | // making the maximum size - maximum!
| |
− | // 10000000 is a "constant" could be found in Apple documentation
| |
− | txt.setMaxSize( NSMakeSize(10000000, 10000000));
| |
− | // preventing textContainer from following the width of NSTextView
| |
− | txt.textContainer.setWidthTracksTextView(false);
| |
− | // making TextContainer large enough.
| |
− | txt.textContainer.setContainerSize ( NSMakeSize( 10000000, 1024));
| |
− | // making NSTextView to resize automatically to the text boundries (max width)
| |
− | txt.setHorizontallyResizable(true);
| |
− | | |
− | NSView(Self.Handle).addSubView(txt);
| |
− | end; </source>
| |
− | | |
− | The next step is actually to embed NSTextView into ScrollView (as a documentView).
| |
− | | |
− | ===Inserting into Scroll View===
| |
− | The process is straight-forward - allocate scroll view, use NSTextView as it's document view
| |
− | <source lang="delphi">
| |
− | procedure TForm1.FormShow(Sender: TObject);
| |
− | var
| |
− | txt : NSTextView;
| |
− | sc : NSScrollView;
| |
− | begin
| |
− | txt := NSTextView.alloc.initWithFrame(NSMakeRect(10,ClientHeight-10-50,50,50));
| |
− | | |
− | txt.setMaxSize( NSMakeSize(10000000, 10000000));
| |
− | txt.textContainer.setWidthTracksTextView(false);
| |
− | txt.textContainer.setContainerSize ( NSMakeSize( 10000000, 1024));
| |
− | txt.setHorizontallyResizable(true);
| |
− | | |
− | // allocating scroll view and placing NSTextView inside
| |
− | sc := NSScrollView.alloc.initWithFrame(NSMakeRect(10,ClientHeight-10-150,150,150));
| |
− | sc.setHasVerticalScroller(true);
| |
− | sc.setHasHorizontalScroller(true);
| |
− | sc.setAutohidesScrollers(true);
| |
− | sc.setDocumentView(txt);
| |
− | | |
− | NSView(Self.Handle).addSubView(sc);
| |
− | end;
| |
− | </source>
| |
− | Now text-view and scrollbars would act as expected.
| |
− | ===Line padding oddity===
| |
− | By default, there's 5 pixels padding between border of NSTextView and left-side of the text.
| |
− | | |
− | It's possible to decrease it, however, setting it to zero is causing a very weird and unpleasant glitch.
| |
− | <source lang="delphi">var
| |
− | txt : NSTextView;
| |
− | sc : NSScrollView;
| |
− | begin
| |
− | txt := NSTextView.alloc.initWithFrame(NSMakeRect(10,ClientHeight-10-50,50,50));
| |
− | | |
− | txt.setMaxSize( NSMakeSize(10000000, 10000000));
| |
− | txt.textContainer.setWidthTracksTextView(false);
| |
− | txt.textContainer.setContainerSize ( NSMakeSize( 10000000, 1024));
| |
− | txt.setHorizontallyResizable(true);
| |
− | | |
− | // setting this value to 0 is causing the problem.
| |
− | txt.textContainer.setLineFragmentPadding(0);
| |
− | | |
− | sc := NSScrollView.alloc.initWithFrame(NSMakeRect(10,ClientHeight-10-150,150,150));
| |
− | sc.setHasVerticalScroller(true);
| |
− | sc.setHasHorizontalScroller(true);
| |
− | sc.setAutohidesScrollers(true);
| |
− | sc.setDocumentView(txt);
| |
− | | |
− | NSView(Self.Handle).addSubView(sc);
| |
− | end;
| |
− | </source>
| |
− | Now. Everytime a new line break is added '''to the end of the text''' the view scrolls to the top (while having cursor at the bottom).
| |
− | | |
− | Either by pressing Enter on keyboard having cursor at the end of the text. Or by inserting a line break at the end of the text programmatically.
| |
− | | |
− | | |
− | The only way to avoid the problem is to have Fragment padding set to a value greater than zero.
| |
− | | |
− | ==See Also==
| |
− | *[[Cocoa Internals]]
| |
− | *[https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TextStorageLayer/Tasks/TrackingSize.html Tracking the Size of a Text View] - Apple's official documentation explains how text size is tracked between NSViewText and NSViewContainer
| |
− | *[https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html Putting an NSTextView Object in an NSScrollView] - Apple's official documentation on how to place NSTextView into a scrollview.
| |
− | *[https://stackoverflow.com/questions/3174140/how-to-disable-word-wrap-of-nstextview How to Disable Word-Wrap of NSTextview] - stackoverflow discussion of the problem.
| |
− | [[Category:Cocoa]]
| |