haiku/headers/os/interface/TextView.h

477 lines
14 KiB
C
Raw Normal View History

/*
IK: align BTextView text rect/fix alignment Recalculate line breaks in FrameResized() if word-wrap is on, otherwise only move the text rect into position. StyledEdit was recalculating line breaks before on resize (we have to in this mode) and the frame offset updates for non-wrapping text views are inexpensive. This makes resizing text view's work like StyledEdit everywhere. Scroll to cursor when word-wrap setting changes if text view is editable. If you are viewing a long document changing word-wrap can move the cursor quite far, so scroll back to it. Fix _ActualTabWidth() pen location for right and center-aligned text views so that tabs widths are calculated correctly. Reset fTextRect horizontal limits to bounds minus insets in _RecalculateLineBreaks(), then grow fTextRect based on alignment when wrap is off. Fixing insets also fixes right and center-aligned BTextViews. Left-aligned text view's grow right, right-aligned ones grow left, and center-aligned ones grow out. Make extra scrolling space for all aligned text views go the other way from how it did in hrev24130 (and on left-aligned text view's too) so that half the text is visible when you edit past the end or before the beginnning of a text view instead of none of it. Fixes #1651 #12608 #13796 #15189 Do not _RecalculateLineBreaks() if text view bounds are invalid. In SetText() detect invalid text view bounds and resize the view to the width and height of the first line. Then recalculate line breaks. This fixes BAlert text view size issues. Fixes #16481 (regression from hrev54496.) Remove useless and heavy computation. There is no point in computing line breaks for a 10px wide text view and it takes a long time because it needs a lot of linebreaks. The view eventually gets laid out properly. Fixes #5582 (which was not locale-related, after all.) Only apply default insets if text rect is set to bounds. This ensures that apps that manipulate the text rect can continue to do so without the default insets interfering while apps that don't can benefit from the defaults. If you want to set the text rect to bounds and not use the default insets you must override the default by calling SetInsets(). This prevent the default insets from being applied once apps have changed the text rect fixing a bug in Icon-O-Matic where the text rect insets were being applied incorrectly. Fixes #16488 (regression from hrev54496.) Reduce left and right insets inside text views from full label spacing to half label spacing. Unify padding between BTextControl and BTextView. Move fLayoutData->UpdateInsets() to private BTextView::_UpdateInsets() because we need access to BTextView member variables when deciding whether or not to add the default padding or not. _UpdateInsets() changes: * Don't update insets if BTextView::SetInsets() was called. * Don't add default insets unless fTextRect is set to view Bounds(). * Do not set the right and bottom insets to left and top if negative, set them to 0 like we do to left and top -- DeskCalc bug otherwise. Fixes #15688 Other BTextView fixes: * Replace max_c and min_c with std::max and std::min respectively. * Remove scrolling from one instance of BTextView::SetText() as it produced undesired results while editing a scrolled text view. * Add default insets in _UpdateInsets() * Fix scrolling when entering and deleting text so that some part of the text is always visible. Make visible scroll width depend on font size. * Allow scrolling to a negative offset in x but not y. This allows you to scroll the entire contents of right and centered-aligned text views whose content does not fit in the box. * Change _Refresh() to take an offset instead of a bool so that you can scroll to any offset. * Replace TextLength() with fText->Length() in a couple of places. TextControl changes: * Set text rect in BTextControl::DoLayout(). * Remove AlignTextRect() from TextInput. Fix the following problems in apps: ScreenSaver: Set text rect in PreviewView::AddPreview(). Tracker: Set "Edit name" text view insets to 2. Tweek text rect position to be on top of label in icon, mini-icon, and list mode. Add a TODO that the text rect is a pixel off from the name on some files. Mail: Remove _AlignTextRect() and FrameResized() from AddressTextControl. Use default insets on the text view, defaults are fine here. DeskCalc: Set insets based on font size in ExpressionTextView SetTextRect() instead of manipulating the text rect. Remove _CheckTextRect() and related methods from InputTextView. Icon-O-Matic: Remove _CheckTextRect() and related methods from InputTextView. WebPositive: Remove _AlignTextRect() and FrameResized() from URLTextView and call SetInsets(). StyledEdit: Word-wrap and FrameResized() changes ported to BTextView. Fixes #16476 #16480 #16488 (regressions from hrev54496.) Change-Id: Ifeca6077f8815ccd86d5a3880f99556298aaf0fe Reviewed-on: https://review.haiku-os.org/c/haiku/+/3152 Reviewed-by: John Scipione <jscipione@gmail.com>
2020-07-20 18:00:41 +03:00
* Copyright 2007-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _TEXTVIEW_H
#define _TEXTVIEW_H
IK: align BTextView text rect/fix alignment Recalculate line breaks in FrameResized() if word-wrap is on, otherwise only move the text rect into position. StyledEdit was recalculating line breaks before on resize (we have to in this mode) and the frame offset updates for non-wrapping text views are inexpensive. This makes resizing text view's work like StyledEdit everywhere. Scroll to cursor when word-wrap setting changes if text view is editable. If you are viewing a long document changing word-wrap can move the cursor quite far, so scroll back to it. Fix _ActualTabWidth() pen location for right and center-aligned text views so that tabs widths are calculated correctly. Reset fTextRect horizontal limits to bounds minus insets in _RecalculateLineBreaks(), then grow fTextRect based on alignment when wrap is off. Fixing insets also fixes right and center-aligned BTextViews. Left-aligned text view's grow right, right-aligned ones grow left, and center-aligned ones grow out. Make extra scrolling space for all aligned text views go the other way from how it did in hrev24130 (and on left-aligned text view's too) so that half the text is visible when you edit past the end or before the beginnning of a text view instead of none of it. Fixes #1651 #12608 #13796 #15189 Do not _RecalculateLineBreaks() if text view bounds are invalid. In SetText() detect invalid text view bounds and resize the view to the width and height of the first line. Then recalculate line breaks. This fixes BAlert text view size issues. Fixes #16481 (regression from hrev54496.) Remove useless and heavy computation. There is no point in computing line breaks for a 10px wide text view and it takes a long time because it needs a lot of linebreaks. The view eventually gets laid out properly. Fixes #5582 (which was not locale-related, after all.) Only apply default insets if text rect is set to bounds. This ensures that apps that manipulate the text rect can continue to do so without the default insets interfering while apps that don't can benefit from the defaults. If you want to set the text rect to bounds and not use the default insets you must override the default by calling SetInsets(). This prevent the default insets from being applied once apps have changed the text rect fixing a bug in Icon-O-Matic where the text rect insets were being applied incorrectly. Fixes #16488 (regression from hrev54496.) Reduce left and right insets inside text views from full label spacing to half label spacing. Unify padding between BTextControl and BTextView. Move fLayoutData->UpdateInsets() to private BTextView::_UpdateInsets() because we need access to BTextView member variables when deciding whether or not to add the default padding or not. _UpdateInsets() changes: * Don't update insets if BTextView::SetInsets() was called. * Don't add default insets unless fTextRect is set to view Bounds(). * Do not set the right and bottom insets to left and top if negative, set them to 0 like we do to left and top -- DeskCalc bug otherwise. Fixes #15688 Other BTextView fixes: * Replace max_c and min_c with std::max and std::min respectively. * Remove scrolling from one instance of BTextView::SetText() as it produced undesired results while editing a scrolled text view. * Add default insets in _UpdateInsets() * Fix scrolling when entering and deleting text so that some part of the text is always visible. Make visible scroll width depend on font size. * Allow scrolling to a negative offset in x but not y. This allows you to scroll the entire contents of right and centered-aligned text views whose content does not fit in the box. * Change _Refresh() to take an offset instead of a bool so that you can scroll to any offset. * Replace TextLength() with fText->Length() in a couple of places. TextControl changes: * Set text rect in BTextControl::DoLayout(). * Remove AlignTextRect() from TextInput. Fix the following problems in apps: ScreenSaver: Set text rect in PreviewView::AddPreview(). Tracker: Set "Edit name" text view insets to 2. Tweek text rect position to be on top of label in icon, mini-icon, and list mode. Add a TODO that the text rect is a pixel off from the name on some files. Mail: Remove _AlignTextRect() and FrameResized() from AddressTextControl. Use default insets on the text view, defaults are fine here. DeskCalc: Set insets based on font size in ExpressionTextView SetTextRect() instead of manipulating the text rect. Remove _CheckTextRect() and related methods from InputTextView. Icon-O-Matic: Remove _CheckTextRect() and related methods from InputTextView. WebPositive: Remove _AlignTextRect() and FrameResized() from URLTextView and call SetInsets(). StyledEdit: Word-wrap and FrameResized() changes ported to BTextView. Fixes #16476 #16480 #16488 (regressions from hrev54496.) Change-Id: Ifeca6077f8815ccd86d5a3880f99556298aaf0fe Reviewed-on: https://review.haiku-os.org/c/haiku/+/3152 Reviewed-by: John Scipione <jscipione@gmail.com>
2020-07-20 18:00:41 +03:00
#include <stdint.h>
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
#include <Locker.h>
#include <View.h>
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
class BBitmap;
class BClipboard;
class BFile;
class BList;
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
class BMessageRunner;
struct text_run {
int32 offset;
BFont font;
rgb_color color;
};
struct text_run_array {
int32 count;
text_run runs[1];
};
enum undo_state {
B_UNDO_UNAVAILABLE,
B_UNDO_TYPING,
B_UNDO_CUT,
B_UNDO_PASTE,
B_UNDO_CLEAR,
B_UNDO_DROP
};
namespace BPrivate {
class TextGapBuffer;
}
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
class BTextView : public BView {
public:
BTextView(BRect frame, const char* name,
BRect textRect, uint32 resizeMask,
uint32 flags
= B_WILL_DRAW | B_PULSE_NEEDED);
BTextView(BRect frame, const char* name,
BRect textRect, const BFont* initialFont,
const rgb_color* initialColor,
uint32 resizeMask, uint32 flags);
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
BTextView(const char* name,
uint32 flags
= B_WILL_DRAW | B_PULSE_NEEDED);
BTextView(const char* name,
const BFont* initialFont,
const rgb_color* initialColor,
uint32 flags);
BTextView(BMessage* archive);
virtual ~BTextView();
static BArchivable* Instantiate(BMessage* archive);
virtual status_t Archive(BMessage* archive,
bool deep = true) const;
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 code,
const BMessage* dragMessage);
2014-06-12 03:00:46 +04:00
virtual void WindowActivated(bool active);
virtual void KeyDown(const char* bytes, int32 numBytes);
virtual void Pulse();
2014-06-12 03:00:46 +04:00
virtual void FrameResized(float newWidth, float newHeight);
virtual void MakeFocus(bool focus = true);
virtual void MessageReceived(BMessage* message);
virtual BHandler* ResolveSpecifier(BMessage* message,
int32 index, BMessage* specifier,
int32 form, const char* property);
virtual status_t GetSupportedSuites(BMessage* data);
virtual status_t Perform(perform_code code, void* data);
void SetText(const char* text,
const text_run_array* runs = NULL);
void SetText(const char* text, int32 length,
const text_run_array* runs = NULL);
void SetText(BFile* file, int32 offset,
int32 length,
const text_run_array* runs = NULL);
void Insert(const char* text,
const text_run_array* runs = NULL);
void Insert(const char* text, int32 length,
const text_run_array* runs = NULL);
void Insert(int32 offset, const char* text,
int32 length,
const text_run_array* runs = NULL);
void Delete();
void Delete(int32 startOffset, int32 endOffset);
const char* Text() const;
int32 TextLength() const;
void GetText(int32 offset, int32 length,
char* buffer) const;
uint8 ByteAt(int32 offset) const;
int32 CountLines() const;
int32 CurrentLine() const;
2014-06-12 03:00:46 +04:00
void GoToLine(int32 lineNumber);
virtual void Cut(BClipboard* clipboard);
virtual void Copy(BClipboard* clipboard);
virtual void Paste(BClipboard* clipboard);
void Clear();
virtual bool AcceptsPaste(BClipboard* clipboard);
virtual bool AcceptsDrop(const BMessage* message);
virtual void Select(int32 startOffset, int32 endOffset);
void SelectAll();
void GetSelection(int32* _start, int32* _end) const;
void SetFontAndColor(const BFont* font,
uint32 mode = B_FONT_ALL,
const rgb_color* color = NULL);
void SetFontAndColor(int32 startOffset,
int32 endOffset, const BFont* font,
uint32 mode = B_FONT_ALL,
const rgb_color* color = NULL);
void GetFontAndColor(int32 offset, BFont* _font,
rgb_color* _color = NULL) const;
void GetFontAndColor(BFont* _font, uint32* _mode,
rgb_color* _color = NULL,
bool* _sameColor = NULL) const;
void SetRunArray(int32 startOffset, int32 endOffset,
const text_run_array* runs);
text_run_array* RunArray(int32 startOffset, int32 endOffset,
int32* _size = NULL) const;
int32 LineAt(int32 offset) const;
int32 LineAt(BPoint point) const;
BPoint PointAt(int32 offset,
float* _height = NULL) const;
int32 OffsetAt(BPoint point) const;
int32 OffsetAt(int32 line) const;
virtual void FindWord(int32 offset, int32* _fromOffset,
int32* _toOffset);
virtual bool CanEndLine(int32 offset);
2014-06-12 03:00:46 +04:00
float LineWidth(int32 lineNumber = 0) const;
float LineHeight(int32 lineNumber = 0) const;
float TextHeight(int32 startLine,
int32 endLine) const;
void GetTextRegion(int32 startOffset,
int32 endOffset, BRegion* outRegion) const;
virtual void ScrollToOffset(int32 offset);
void ScrollToSelection();
void Highlight(int32 startOffset, int32 endOffset);
void SetTextRect(BRect rect);
BRect TextRect() const;
void SetInsets(float left, float top, float right,
float bottom);
void GetInsets(float* _left, float* _top,
float* _right, float* _bottom) const;
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
void SetStylable(bool stylable);
bool IsStylable() const;
void SetTabWidth(float width);
float TabWidth() const;
void MakeSelectable(bool selectable = true);
bool IsSelectable() const;
void MakeEditable(bool editable = true);
bool IsEditable() const;
void SetWordWrap(bool wrap);
bool DoesWordWrap() const;
void SetMaxBytes(int32 max);
int32 MaxBytes() const;
void DisallowChar(uint32 character);
void AllowChar(uint32 character);
void SetAlignment(alignment align);
alignment Alignment() const;
void SetAutoindent(bool state);
bool DoesAutoindent() const;
void SetColorSpace(color_space colors);
color_space ColorSpace() const;
void MakeResizable(bool resize,
BView* resizeView = NULL);
bool IsResizable() const;
void SetDoesUndo(bool undo);
bool DoesUndo() const;
void HideTyping(bool enabled);
bool IsTypingHidden() const;
virtual void ResizeToPreferred();
virtual void GetPreferredSize(float* _width, float* _height);
virtual void AllAttached();
virtual void AllDetached();
static text_run_array* AllocRunArray(int32 entryCount,
int32* outSize = NULL);
static text_run_array* CopyRunArray(const text_run_array* orig,
int32 countDelta = 0);
static void FreeRunArray(text_run_array* array);
static void* FlattenRunArray(const text_run_array* runArray,
int32* _size = NULL);
static text_run_array* UnflattenRunArray(const void* data,
int32* _size = NULL);
protected:
virtual void InsertText(const char* text, int32 length,
int32 offset, const text_run_array* runs);
virtual void DeleteText(int32 fromOffset, int32 toOffset);
public:
virtual void Undo(BClipboard* clipboard);
undo_state UndoState(bool* isRedo) const;
protected:
virtual void GetDragParameters(BMessage* drag,
BBitmap** _bitmap, BPoint* point,
BHandler** _handler);
virtual void LayoutInvalidated(bool descendants);
virtual void DoLayout();
public:
virtual BSize MinSize();
virtual BSize MaxSize();
virtual BSize PreferredSize();
virtual bool HasHeightForWidth();
virtual void GetHeightForWidth(float width, float* min,
float* max, float* preferred);
private:
// FBC padding and forbidden methods
virtual void _ReservedTextView3();
virtual void _ReservedTextView4();
virtual void _ReservedTextView5();
virtual void _ReservedTextView6();
virtual void _ReservedTextView7();
virtual void _ReservedTextView8();
virtual void _ReservedTextView9();
virtual void _ReservedTextView10();
virtual void _ReservedTextView11();
virtual void _ReservedTextView12();
private:
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
class InlineInput;
struct LayoutData;
class LineBuffer;
class StyleBuffer;
class TextTrackState;
class UndoBuffer;
// UndoBuffer derivatives
class CutUndoBuffer;
class PasteUndoBuffer;
class ClearUndoBuffer;
class DropUndoBuffer;
class TypingUndoBuffer;
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
friend class TextTrackState;
void _InitObject(BRect textRect,
const BFont* initialFont,
const rgb_color* initialColor);
void _ValidateLayoutData();
void _ResetTextRect();
void _HandleBackspace(int32 modifiers = -1);
void _HandleArrowKey(uint32 arrowKey,
int32 modifiers = -1);
void _HandleDelete(int32 modifiers = -1);
void _HandlePageKey(uint32 pageKey,
int32 modifiers = -1);
void _HandleAlphaKey(const char* bytes,
int32 numBytes);
void _Refresh(int32 fromOffset, int32 toOffset,
IK: align BTextView text rect/fix alignment Recalculate line breaks in FrameResized() if word-wrap is on, otherwise only move the text rect into position. StyledEdit was recalculating line breaks before on resize (we have to in this mode) and the frame offset updates for non-wrapping text views are inexpensive. This makes resizing text view's work like StyledEdit everywhere. Scroll to cursor when word-wrap setting changes if text view is editable. If you are viewing a long document changing word-wrap can move the cursor quite far, so scroll back to it. Fix _ActualTabWidth() pen location for right and center-aligned text views so that tabs widths are calculated correctly. Reset fTextRect horizontal limits to bounds minus insets in _RecalculateLineBreaks(), then grow fTextRect based on alignment when wrap is off. Fixing insets also fixes right and center-aligned BTextViews. Left-aligned text view's grow right, right-aligned ones grow left, and center-aligned ones grow out. Make extra scrolling space for all aligned text views go the other way from how it did in hrev24130 (and on left-aligned text view's too) so that half the text is visible when you edit past the end or before the beginnning of a text view instead of none of it. Fixes #1651 #12608 #13796 #15189 Do not _RecalculateLineBreaks() if text view bounds are invalid. In SetText() detect invalid text view bounds and resize the view to the width and height of the first line. Then recalculate line breaks. This fixes BAlert text view size issues. Fixes #16481 (regression from hrev54496.) Remove useless and heavy computation. There is no point in computing line breaks for a 10px wide text view and it takes a long time because it needs a lot of linebreaks. The view eventually gets laid out properly. Fixes #5582 (which was not locale-related, after all.) Only apply default insets if text rect is set to bounds. This ensures that apps that manipulate the text rect can continue to do so without the default insets interfering while apps that don't can benefit from the defaults. If you want to set the text rect to bounds and not use the default insets you must override the default by calling SetInsets(). This prevent the default insets from being applied once apps have changed the text rect fixing a bug in Icon-O-Matic where the text rect insets were being applied incorrectly. Fixes #16488 (regression from hrev54496.) Reduce left and right insets inside text views from full label spacing to half label spacing. Unify padding between BTextControl and BTextView. Move fLayoutData->UpdateInsets() to private BTextView::_UpdateInsets() because we need access to BTextView member variables when deciding whether or not to add the default padding or not. _UpdateInsets() changes: * Don't update insets if BTextView::SetInsets() was called. * Don't add default insets unless fTextRect is set to view Bounds(). * Do not set the right and bottom insets to left and top if negative, set them to 0 like we do to left and top -- DeskCalc bug otherwise. Fixes #15688 Other BTextView fixes: * Replace max_c and min_c with std::max and std::min respectively. * Remove scrolling from one instance of BTextView::SetText() as it produced undesired results while editing a scrolled text view. * Add default insets in _UpdateInsets() * Fix scrolling when entering and deleting text so that some part of the text is always visible. Make visible scroll width depend on font size. * Allow scrolling to a negative offset in x but not y. This allows you to scroll the entire contents of right and centered-aligned text views whose content does not fit in the box. * Change _Refresh() to take an offset instead of a bool so that you can scroll to any offset. * Replace TextLength() with fText->Length() in a couple of places. TextControl changes: * Set text rect in BTextControl::DoLayout(). * Remove AlignTextRect() from TextInput. Fix the following problems in apps: ScreenSaver: Set text rect in PreviewView::AddPreview(). Tracker: Set "Edit name" text view insets to 2. Tweek text rect position to be on top of label in icon, mini-icon, and list mode. Add a TODO that the text rect is a pixel off from the name on some files. Mail: Remove _AlignTextRect() and FrameResized() from AddressTextControl. Use default insets on the text view, defaults are fine here. DeskCalc: Set insets based on font size in ExpressionTextView SetTextRect() instead of manipulating the text rect. Remove _CheckTextRect() and related methods from InputTextView. Icon-O-Matic: Remove _CheckTextRect() and related methods from InputTextView. WebPositive: Remove _AlignTextRect() and FrameResized() from URLTextView and call SetInsets(). StyledEdit: Word-wrap and FrameResized() changes ported to BTextView. Fixes #16476 #16480 #16488 (regressions from hrev54496.) Change-Id: Ifeca6077f8815ccd86d5a3880f99556298aaf0fe Reviewed-on: https://review.haiku-os.org/c/haiku/+/3152 Reviewed-by: John Scipione <jscipione@gmail.com>
2020-07-20 18:00:41 +03:00
int32 scrollTo = INT32_MIN);
void _RecalculateLineBreaks(int32* startLine,
int32* endLine);
BTextView: Fix Tracker edit name Don't resize text view in FrameResized() if resizable, this is done in _AutoResize() instead. Set text rect width to width of max line when word-wrap is off. Text rect width shrinks to the width of the text matching behavior of BeOS R5 and previous Haiku. This fixes Tracker Edit name. Limit max width to column width in list mode or 30em in icon mode. Filter paste messages limiting to max width in Tracker Edit name. General BTextView fixes: As a consequence of the text rect shrinking to fit the text, adjust highlighting to go at least to edge of the view even if text rect width is narrower. Extend the invalidation area beyond text rect when redrawing to include highlighted areas. Text views behave properly when overflow occurs i.e. when you type text off the end of the text view. The text is nudged over as you type/scroll so that the previous text is visible. This sorta worked before but now works better. Fix text rect centering by replacing switch with BLayoutUtils::AlignOnRect(). Coalesce consecutive draw calls when inserting and deleting text to prevent flashing for example when resizing the window. Redraw text when the text view scrolls fixing a bug I noticed in StyledEdit. Workaround negative height Beezer bug. Fixes #16642, #16476 Change-Id: I2d32d6039944d2dc3218ce4de71f2966cc98c866 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3642 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
2021-01-17 22:57:07 +03:00
void _ValidateTextRect();
int32 _FindLineBreak(int32 fromOffset,
float* _ascent, float* _descent,
float* inOutWidth);
float _StyledWidth(int32 fromOffset, int32 length,
float* _ascent = NULL,
float* _descent = NULL) const;
float _TabExpandedStyledWidth(int32 offset,
int32 length, float* _ascent = NULL,
float* _descent = NULL) const;
float _ActualTabWidth(float location) const;
void _DoInsertText(const char* text, int32 length,
int32 offset, const text_run_array* runs);
void _DoDeleteText(int32 fromOffset,
int32 toOffset);
void _DrawLine(BView* view, const int32 &startLine,
const int32& startOffset,
const bool& erase, BRect& eraseRect,
BRegion& inputRegion);
void _DrawLines(int32 startLine, int32 endLine,
int32 startOffset = -1,
bool erase = false);
void _RequestDrawLines(int32 startLine,
int32 endLine);
void _DrawCaret(int32 offset, bool visible);
void _ShowCaret();
void _HideCaret();
void _InvertCaret();
void _DragCaret(int32 offset);
void _StopMouseTracking();
bool _PerformMouseUp(BPoint where);
bool _PerformMouseMoved(BPoint where, uint32 code);
void _TrackMouse(BPoint where,
const BMessage* message,
bool force = false);
void _TrackDrag(BPoint where);
void _InitiateDrag();
bool _MessageDropped(BMessage* message,
BPoint where, BPoint offset);
void _PerformAutoScrolling();
void _UpdateScrollbars();
void _ScrollBy(float horizontalStep,
float verticalStep);
void _ScrollTo(float x, float y);
void _AutoResize(bool doRedraw = true);
void _NewOffscreen(float padding = 0.0);
void _DeleteOffscreen();
void _Activate();
void _Deactivate();
void _NormalizeFont(BFont* font);
void _SetRunArray(int32 startOffset, int32 endOffset,
const text_run_array* runs);
void _ApplyStyleRange(int32 fromOffset,
int32 toOffset,
uint32 mode = B_FONT_ALL,
const BFont* font = NULL,
const rgb_color* color = NULL,
bool syncNullStyle = true);
uint32 _CharClassification(int32 offset) const;
int32 _NextInitialByte(int32 offset) const;
int32 _PreviousInitialByte(int32 offset) const;
int32 _PreviousLineStart(int32 offset);
int32 _NextLineEnd(int32 offset);
int32 _PreviousWordBoundary(int32 offset);
int32 _NextWordBoundary(int32 offset);
int32 _PreviousWordStart(int32 offset);
int32 _NextWordEnd(int32 offset);
bool _GetProperty(BMessage* message,
BMessage* specifier,
const char* property, BMessage* reply);
bool _SetProperty(BMessage* message,
BMessage* specifier,
const char* property, BMessage* reply);
bool _CountProperties(BMessage* message,
BMessage* specifier, const char* property,
BMessage* reply);
void _HandleInputMethodChanged(BMessage* message);
void _HandleInputMethodLocationRequest();
void _CancelInputMethod();
int32 _LineAt(int32 offset) const;
int32 _LineAt(const BPoint& point) const;
bool _IsOnEmptyLastLine(int32 offset) const;
float _NullStyleHeight() const;
void _ShowContextMenu(BPoint where);
void _FilterDisallowedChars(char* text,
ssize_t& length, text_run_array* runArray);
IK: align BTextView text rect/fix alignment Recalculate line breaks in FrameResized() if word-wrap is on, otherwise only move the text rect into position. StyledEdit was recalculating line breaks before on resize (we have to in this mode) and the frame offset updates for non-wrapping text views are inexpensive. This makes resizing text view's work like StyledEdit everywhere. Scroll to cursor when word-wrap setting changes if text view is editable. If you are viewing a long document changing word-wrap can move the cursor quite far, so scroll back to it. Fix _ActualTabWidth() pen location for right and center-aligned text views so that tabs widths are calculated correctly. Reset fTextRect horizontal limits to bounds minus insets in _RecalculateLineBreaks(), then grow fTextRect based on alignment when wrap is off. Fixing insets also fixes right and center-aligned BTextViews. Left-aligned text view's grow right, right-aligned ones grow left, and center-aligned ones grow out. Make extra scrolling space for all aligned text views go the other way from how it did in hrev24130 (and on left-aligned text view's too) so that half the text is visible when you edit past the end or before the beginnning of a text view instead of none of it. Fixes #1651 #12608 #13796 #15189 Do not _RecalculateLineBreaks() if text view bounds are invalid. In SetText() detect invalid text view bounds and resize the view to the width and height of the first line. Then recalculate line breaks. This fixes BAlert text view size issues. Fixes #16481 (regression from hrev54496.) Remove useless and heavy computation. There is no point in computing line breaks for a 10px wide text view and it takes a long time because it needs a lot of linebreaks. The view eventually gets laid out properly. Fixes #5582 (which was not locale-related, after all.) Only apply default insets if text rect is set to bounds. This ensures that apps that manipulate the text rect can continue to do so without the default insets interfering while apps that don't can benefit from the defaults. If you want to set the text rect to bounds and not use the default insets you must override the default by calling SetInsets(). This prevent the default insets from being applied once apps have changed the text rect fixing a bug in Icon-O-Matic where the text rect insets were being applied incorrectly. Fixes #16488 (regression from hrev54496.) Reduce left and right insets inside text views from full label spacing to half label spacing. Unify padding between BTextControl and BTextView. Move fLayoutData->UpdateInsets() to private BTextView::_UpdateInsets() because we need access to BTextView member variables when deciding whether or not to add the default padding or not. _UpdateInsets() changes: * Don't update insets if BTextView::SetInsets() was called. * Don't add default insets unless fTextRect is set to view Bounds(). * Do not set the right and bottom insets to left and top if negative, set them to 0 like we do to left and top -- DeskCalc bug otherwise. Fixes #15688 Other BTextView fixes: * Replace max_c and min_c with std::max and std::min respectively. * Remove scrolling from one instance of BTextView::SetText() as it produced undesired results while editing a scrolled text view. * Add default insets in _UpdateInsets() * Fix scrolling when entering and deleting text so that some part of the text is always visible. Make visible scroll width depend on font size. * Allow scrolling to a negative offset in x but not y. This allows you to scroll the entire contents of right and centered-aligned text views whose content does not fit in the box. * Change _Refresh() to take an offset instead of a bool so that you can scroll to any offset. * Replace TextLength() with fText->Length() in a couple of places. TextControl changes: * Set text rect in BTextControl::DoLayout(). * Remove AlignTextRect() from TextInput. Fix the following problems in apps: ScreenSaver: Set text rect in PreviewView::AddPreview(). Tracker: Set "Edit name" text view insets to 2. Tweek text rect position to be on top of label in icon, mini-icon, and list mode. Add a TODO that the text rect is a pixel off from the name on some files. Mail: Remove _AlignTextRect() and FrameResized() from AddressTextControl. Use default insets on the text view, defaults are fine here. DeskCalc: Set insets based on font size in ExpressionTextView SetTextRect() instead of manipulating the text rect. Remove _CheckTextRect() and related methods from InputTextView. Icon-O-Matic: Remove _CheckTextRect() and related methods from InputTextView. WebPositive: Remove _AlignTextRect() and FrameResized() from URLTextView and call SetInsets(). StyledEdit: Word-wrap and FrameResized() changes ported to BTextView. Fixes #16476 #16480 #16488 (regressions from hrev54496.) Change-Id: Ifeca6077f8815ccd86d5a3880f99556298aaf0fe Reviewed-on: https://review.haiku-os.org/c/haiku/+/3152 Reviewed-by: John Scipione <jscipione@gmail.com>
2020-07-20 18:00:41 +03:00
void _UpdateInsets(const BRect& rect);
private:
BPrivate::TextGapBuffer* fText;
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
LineBuffer* fLines;
StyleBuffer* fStyles;
BRect fTextRect;
int32 fSelStart;
int32 fSelEnd;
bool fCaretVisible;
bigtime_t fCaretTime;
int32 fCaretOffset;
int32 fClickCount;
bigtime_t fClickTime;
int32 fDragOffset;
uint8 fCursor;
bool fActive;
bool fStylable;
float fTabWidth;
bool fSelectable;
bool fEditable;
bool fWrap;
int32 fMaxBytes;
BList* fDisallowedChars;
alignment fAlignment;
bool fAutoindent;
BBitmap* fOffscreen;
color_space fColorSpace;
bool fResizable;
BView* fContainerView;
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
UndoBuffer* fUndo;
InlineInput* fInline;
BMessageRunner* fDragRunner;
BMessageRunner* fClickRunner;
BPoint fWhere;
Quite a cleanup action to avoid polluting the global namespace with private BTextView classes: * Declared the directly used BTextView helper classes as private BTextView classes and changed all affected files. * Realized that Tracker's BPoseView was (accidentally?) using what used to be _BWidthBuffer_. It had declared it's own class with the same name and same members/size in headers/private/tracker/TextViewSupport.h, but the implementation was nowhere to be found. I can only explain this that the BTextView implementation was then actually linked and used. But the big problem was that it was used without locking (unlike in BTextView)! When many Tracker windows opened during system startup or later and they happened to each request characters not yet in the cache, I imagine things could have gone bad and corrupted memory. Anyways, since I can see the usefulness of the cache, BPoseView uses BTextView::WidthBuffer on purpose now. And I moved the locking inside BTextView::WidthBuffer::StringWidth(). * Adjusted InterfaceDefs.cpp accordingly. * TODO: Move subsequent classes into BTextView namespace as well, ie derived classes that BTextView doesn't directly know about. All stuff in src/kits/ inteface/textview_support/ * Added preliminary and not yet implemented layout friendly BTextView constructors. * I will try to handle the insets imposed by BTextView::fTextRect a bit differently when used inside the new layout management framework. For this, I added BTextView::SetInsets() and GetInsets(). SetInsets() doesn't do anything yet. So far, everything seems to work still... ;-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27654 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-09-20 19:08:40 +04:00
TextTrackState* fTrackingMouse;
float fMinTextRectWidth;
LayoutData* fLayoutData;
int32 fLastClickOffset;
bool fInstalledNavigateCommandWordwiseShortcuts : 1;
bool fInstalledNavigateOptionWordwiseShortcuts : 1;
bool fInstalledNavigateOptionLinewiseShortcuts : 1;
bool fInstalledNavigateHomeEndDocwiseShortcuts : 1;
bool fInstalledSelectCommandWordwiseShortcuts : 1;
bool fInstalledSelectOptionWordwiseShortcuts : 1;
bool fInstalledSelectOptionLinewiseShortcuts : 1;
bool fInstalledSelectHomeEndDocwiseShortcuts : 1;
bool fInstalledRemoveCommandWordwiseShortcuts : 1;
bool fInstalledRemoveOptionWordwiseShortcuts : 1;
uint32 _reserved[6];
};
#endif // _TEXTVIEW_H