hrev46661 adds 3 changesets to branch 'master' old head: d1c7f766fde371e1b4a7e188e3889f26ebdd04a8 new head: 130db54051570a3eaa11deb64ca7971d40b0be76 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=130db54+%5Ed1c7f76 ---------------------------------------------------------------------------- 810f0a4: IconUtis.cpp: Fixed cast. 85ad88c: HaikuDepot: Added simple TextSelection class. 130db54: HaikuDepot: Added work-in-progress TextEditor class The intention here is to be able to set it on a TextDocumentView to add editing capabilities. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- 6 files changed, 547 insertions(+), 8 deletions(-) src/apps/haiku-depot/Jamfile | 2 + src/apps/haiku-depot/textview/TextEditor.cpp | 345 ++++++++++++++++++++ src/apps/haiku-depot/textview/TextEditor.h | 85 +++++ src/apps/haiku-depot/textview/TextSelection.cpp | 72 ++++ src/apps/haiku-depot/textview/TextSelection.h | 36 ++ src/libs/icon/IconUtils.cpp | 15 +- ############################################################################ Commit: 810f0a42e50b32d17c478f0bdf73b1b34d315ad0 URL: http://cgit.haiku-os.org/haiku/commit/?id=810f0a4 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sun Jan 12 12:47:30 2014 UTC IconUtis.cpp: Fixed cast. ---------------------------------------------------------------------------- diff --git a/src/libs/icon/IconUtils.cpp b/src/libs/icon/IconUtils.cpp index 6400c4d..bbefa87 100644 --- a/src/libs/icon/IconUtils.cpp +++ b/src/libs/icon/IconUtils.cpp @@ -149,14 +149,13 @@ scale_down(const uint8* srcBits, uint8* dstBits, int32 srcWidth, int32 srcHeight p4 = *((uint32*)srcBits + ((l + 1)* srcWidth) + c); // color components - blue = (uint8)p1 * d1 + (uint8)p2 * d2 + (uint8)p3 * d3 - + (uint8)p4 * d4; - green = (uint8)(p1 >> 8) * d1 + (uint8)(p2 >> 8) * d2 - + (uint8)(p3 >> 8) * d3 + (uint8)(p4 >> 8) * d4; - red = (uint8)(p1 >> 16) * d1 + (uint8)(p2 >> 16) * d2 - + (uint8)(p3 >> 16) * d3 + (uint8)(p4 >> 16) * d4; - alpha = (uint8)(p1 >> 24) * d1 + (uint8)(p2 >> 24) * d2 - + (uint8)(p3 >> 24) * d3 + (uint8)(p4 >> 24) * d4; + blue = (uint8)(p1 * d1 + p2 * d2 + p3 * d3 + p4 * d4); + green = (uint8)((p1 >> 8) * d1 + (p2 >> 8) * d2 + + (p3 >> 8) * d3 + (p4 >> 8) * d4); + red = (uint8)((p1 >> 16) * d1 + (p2 >> 16) * d2 + + (p3 >> 16) * d3 + (p4 >> 16) * d4); + alpha = (uint8)((p1 >> 24) * d1 + (p2 >> 24) * d2 + + (p3 >> 24) * d3 + (p4 >> 24) * d4); // destination RGBA pixel *((uint32*)dstBits + (i * dstWidth) + j) ############################################################################ Commit: 85ad88c67e0a8f799e4a15b649f6e72635542450 URL: http://cgit.haiku-os.org/haiku/commit/?id=85ad88c Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sun Jan 12 12:53:16 2014 UTC HaikuDepot: Added simple TextSelection class. ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/TextSelection.cpp b/src/apps/haiku-depot/textview/TextSelection.cpp new file mode 100644 index 0000000..c84facf --- /dev/null +++ b/src/apps/haiku-depot/textview/TextSelection.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "TextSelection.h" + + +TextSelection::TextSelection() + : + fAnchor(0), + fCaret(0) +{ +} + + +TextSelection::TextSelection(int32 anchor, int32 caret) + : + fAnchor(anchor), + fCaret(caret) +{ +} + + +TextSelection::TextSelection(const TextSelection& other) + : + fAnchor(other.fAnchor), + fCaret(other.fCaret) +{ +} + + +TextSelection& +TextSelection::operator=(const TextSelection& other) +{ + if (this == &other) + return *this; + + fAnchor = other.fAnchor; + fCaret = other.fCaret; + return *this; +} + + +bool +TextSelection::operator==(const TextSelection& other) const +{ + return (this == &other) + || (fAnchor == other.fAnchor && fCaret == other.fCaret); +} + + +bool +TextSelection::operator!=(const TextSelection& other) const +{ + return !(*this == other); +} + + +void +TextSelection::SetAnchor(int32 anchor) +{ + fAnchor = anchor; +} + + +void +TextSelection::SetCaret(int32 caret) +{ + fCaret = caret; +} + diff --git a/src/apps/haiku-depot/textview/TextSelection.h b/src/apps/haiku-depot/textview/TextSelection.h new file mode 100644 index 0000000..8fa98e0 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextSelection.h @@ -0,0 +1,36 @@ +/* + * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef TEXT_SELECTION_H +#define TEXT_SELECTION_H + + +#include <SupportDefs.h> + + +class TextSelection { +public: + TextSelection(); + TextSelection(int32 anchor, int32 caret); + TextSelection(const TextSelection& other); + + TextSelection& operator=(const TextSelection& other); + bool operator==(const TextSelection& other) const; + bool operator!=(const TextSelection& other) const; + + void SetAnchor(int32 anchor); + inline int32 Anchor() const + { return fAnchor; } + + void SetCaret(int32 caret); + inline int32 Caret() const + { return fCaret; } + +private: + int32 fAnchor; + int32 fCaret; +}; + + +#endif // TEXT_SELECTION_H ############################################################################ Revision: hrev46661 Commit: 130db54051570a3eaa11deb64ca7971d40b0be76 URL: http://cgit.haiku-os.org/haiku/commit/?id=130db54 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Sun Jan 12 12:54:03 2014 UTC HaikuDepot: Added work-in-progress TextEditor class The intention here is to be able to set it on a TextDocumentView to add editing capabilities. ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/Jamfile b/src/apps/haiku-depot/Jamfile index 602671e..899aa60 100644 --- a/src/apps/haiku-depot/Jamfile +++ b/src/apps/haiku-depot/Jamfile @@ -26,6 +26,8 @@ local textDocumentSources = TextDocument.cpp TextDocumentLayout.cpp TextDocumentView.cpp + TextEditor.cpp + TextSelection.cpp TextSpan.cpp TextView.cpp ; diff --git a/src/apps/haiku-depot/textview/TextEditor.cpp b/src/apps/haiku-depot/textview/TextEditor.cpp new file mode 100644 index 0000000..f3a28b3 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextEditor.cpp @@ -0,0 +1,345 @@ +/* + * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "TextEditor.h" + +#include <algorithm> + + +TextEditor::TextEditor() + : + fDocument(), + fLayout(), + fSelection(), + fCaretAnchorX(0.0f), + fStyleAtCaret() +{ +} + + +TextEditor::TextEditor(const TextEditor& other) + : + fDocument(other.fDocument), + fLayout(other.fLayout), + fSelection(other.fSelection), + fCaretAnchorX(other.fCaretAnchorX), + fStyleAtCaret(other.fStyleAtCaret) +{ +} + + +TextEditor& +TextEditor::operator=(const TextEditor& other) +{ + if (this == &other) + return *this; + + fDocument = other.fDocument; + fLayout = other.fLayout; + fSelection = other.fSelection; + fCaretAnchorX = other.fCaretAnchorX; + fStyleAtCaret = other.fStyleAtCaret; + return *this; +} + + +bool +TextEditor::operator==(const TextEditor& other) const +{ + if (this == &other) + return true; + + return fDocument == other.fDocument + && fLayout == other.fLayout + && fSelection == other.fSelection + && fCaretAnchorX == other.fCaretAnchorX + && fStyleAtCaret == other.fStyleAtCaret; +} + + +bool +TextEditor::operator!=(const TextEditor& other) const +{ + return !(*this == other); +} + + +// #pragma mark - + + +void +TextEditor::SetDocument(const TextDocumentRef& ref) +{ + fDocument = ref; + SetSelection(TextSelection()); +} + + +void +TextEditor::SetLayout(const TextDocumentLayoutRef& ref) +{ + fLayout = ref; + SetSelection(TextSelection()); +} + + +void +TextEditor::SetSelection(TextSelection selection) +{ + _SetSelection(selection.Caret(), selection.Anchor(), true, true); +} + + +void +TextEditor::SetCharacterStyle(::CharacterStyle style) +{ + if (fStyleAtCaret == style) + return; + + fStyleAtCaret = style; + + if (fSelection.Caret() != fSelection.Anchor()) { + // TODO: Apply style to selection range + } +} + + +void +TextEditor::KeyDown(KeyEvent event) +{ + if (fDocument.Get() == NULL) + return; + + bool select = (event.modifiers & B_SHIFT_KEY) != 0; + + switch (event.key) { + case B_UP_ARROW: + _LineUp(select); + break; + + case B_DOWN_ARROW: + _LineDown(select); + break; + + case B_LEFT_ARROW: + if (_HasSelection() && !select) { + _SetCaretOffset( + std::min(fSelection.Caret(), fSelection.Anchor()), + true, false, true + ); + } else + _SetCaretOffset(fSelection.Caret() - 1, true, select, true); + break; + + case B_RIGHT_ARROW: + if (_HasSelection() && !select) { + _SetCaretOffset( + std::max(fSelection.Caret(), fSelection.Anchor()), + true, false, true + ); + } else + _SetCaretOffset(fSelection.Caret() + 1, true, select, true); + break; + + case B_HOME: + _LineStart(select); + break; + + case B_END: + _LineEnd(select); + break; + + case B_ENTER: + Insert(fSelection.Caret(), "\n"); + break; + + case B_TAB: + // TODO: Tab support in TextLayout + Insert(fSelection.Caret(), " "); + break; + + case B_ESCAPE: + break; + + case B_BACKSPACE: + if (_HasSelection()) { + Remove(_SelectionStart(), _SelectionLength()); + } else { + if (fSelection.Caret() > 0) + Remove(fSelection.Caret() - 1, 1); + } + break; + + case B_DELETE: + if (_HasSelection()) { + Remove(_SelectionStart(), _SelectionLength()); + } else { + if (fSelection.Caret() < fDocument->Length()) + Remove(fSelection.Caret(), 1); + } + break; + + case B_INSERT: + // TODO: Toggle insert mode (or maybe just don't support it) + break; + + case B_PAGE_UP: + case B_PAGE_DOWN: + case B_SUBSTITUTE: + case B_FUNCTION_KEY: + case B_KATAKANA_HIRAGANA: + case B_HANKAKU_ZENKAKU: + break; + + default: + if (event.bytes != NULL && event.length > 0) { + // Handle null-termintating the string + BString text(event.bytes, event.length); + Insert(fSelection.Caret(), text); + } + break; + } +} + + +void +TextEditor::Insert(int32 offset, const BString& string) +{ + // TODO: ... +} + + +void +TextEditor::Remove(int32 offset, int32 length) +{ + // TODO: ... +} + + +// #pragma mark - private + + +// _SetCaretOffset +void +TextEditor::_SetCaretOffset(int32 offset, bool updateAnchor, + bool lockSelectionAnchor, bool updateSelectionStyle) +{ + if (fDocument.Get() == NULL) + return; + + if (offset < 0) + offset = 0; + int32 textLength = fDocument->Length(); + if (offset > textLength) + offset = textLength; + + int32 caret = offset; + int32 anchor = lockSelectionAnchor ? fSelection.Anchor() : offset; + _SetSelection(caret, anchor, updateAnchor, updateSelectionStyle); +} + + +// _SetSelection +void +TextEditor::_SetSelection(int32 caret, int32 anchor, bool updateAnchor, + bool updateSelectionStyle) +{ + if (fLayout.Get() == NULL) + return; + + if (caret == fSelection.Caret() && caret == fSelection.Anchor()) + return; + + fSelection.SetAnchor(anchor); + fSelection.SetCaret(caret); + + if (updateAnchor) { + float x1; + float y1; + float x2; + float y2; + + fLayout->GetTextBounds(caret, x1, y1, x2, y2); + fCaretAnchorX = x1; + } + + if (updateSelectionStyle) + _UpdateStyleAtCaret(); +} + + +void +TextEditor::_UpdateStyleAtCaret() +{ + if (fDocument.Get() == NULL) + return; + + int32 offset = fSelection.Caret() - 1; + if (offset < 0) + offset = 0; + SetCharacterStyle(fDocument->CharacterStyleAt(offset)); +} + + +// #pragma mark - + + +void +TextEditor::_LineUp(bool select) +{ + // TODO +} + + +void +TextEditor::_LineDown(bool select) +{ + // TODO +} + + +void +TextEditor::_LineStart(bool select) +{ + // TODO +} + + +void +TextEditor::_LineEnd(bool select) +{ + // TODO +} + + +// #pragma mark - + + +bool +TextEditor::_HasSelection() const +{ + return _SelectionLength() > 0; +} + + +int32 +TextEditor::_SelectionStart() const +{ + return std::min(fSelection.Caret(), fSelection.Anchor()); +} + + +int32 +TextEditor::_SelectionEnd() const +{ + return std::max(fSelection.Caret(), fSelection.Anchor()); +} + + +int32 +TextEditor::_SelectionLength() const +{ + return _SelectionEnd() - _SelectionStart(); +} diff --git a/src/apps/haiku-depot/textview/TextEditor.h b/src/apps/haiku-depot/textview/TextEditor.h new file mode 100644 index 0000000..c52c4b2 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextEditor.h @@ -0,0 +1,85 @@ +/* + * Copyright 2014, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef TEXT_EDITOR_H +#define TEXT_EDITOR_H + + +#include "CharacterStyle.h" +#include "TextDocument.h" +#include "TextDocumentLayout.h" +#include "TextSelection.h" + + +class KeyEvent { +public: + const char* bytes; + int32 length; + int32 key; + int32 modifiers; +}; + + +class TextEditor { +public: + TextEditor(); + TextEditor(const TextEditor& other); + + TextEditor& operator=(const TextEditor& other); + bool operator==(const TextEditor& other) const; + bool operator!=(const TextEditor& other) const; + + void SetDocument(const TextDocumentRef& ref); + TextDocumentRef Document() const + { return fDocument; } + + void SetLayout( + const TextDocumentLayoutRef& ref); + TextDocumentLayoutRef Layout() const + { return fLayout; } + + void SetSelection(TextSelection selection); + inline TextSelection Selection() const + { return fSelection; } + + void SetCharacterStyle(::CharacterStyle style); + ::CharacterStyle CharacterStyle() const + { return fStyleAtCaret; } + + void KeyDown(KeyEvent event); + + void Insert(int32 offset, const BString& string); + void Remove(int32 offset, int32 length); + +private: + void _SetCaretOffset(int32 offset, + bool updateAnchor, + bool lockSelectionAnchor, + bool updateSelectionStyle); + void _SetSelection(int32 caret, int32 anchor, + bool updateAnchor, + bool updateSelectionStyle); + + void _UpdateStyleAtCaret(); + + void _LineUp(bool select); + void _LineDown(bool select); + void _LineStart(bool select); + void _LineEnd(bool select); + + bool _HasSelection() const; + int32 _SelectionStart() const; + int32 _SelectionEnd() const; + int32 _SelectionLength() const; + +private: + TextDocumentRef fDocument; + TextDocumentLayoutRef fLayout; + TextSelection fSelection; + float fCaretAnchorX; + ::CharacterStyle fStyleAtCaret; +}; + + +#endif // TEXT_EDITOR_H