From 6adf049cfaed26c0eea32ed75ce6bdd979cdaccd Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 19 Jul 2004 14:38:35 +0000 Subject: [PATCH] Inline input method handling for BTextView (still lacks the blue/red highlighting). Thanks to Andrew and Koki for the hints. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8431 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/interface/BTextView/InlineInput.cpp | 69 +++++++++ src/kits/interface/BTextView/InlineInput.h | 31 ++++ src/kits/interface/BTextView/Jamfile | 1 + src/kits/interface/BTextView/StyleBuffer.cpp | 3 +- src/kits/interface/BTextView/StyleBuffer.h | 3 +- src/kits/interface/BTextView/TextView.cpp | 148 ++++++++++++++++--- 6 files changed, 229 insertions(+), 26 deletions(-) create mode 100644 src/kits/interface/BTextView/InlineInput.cpp create mode 100644 src/kits/interface/BTextView/InlineInput.h diff --git a/src/kits/interface/BTextView/InlineInput.cpp b/src/kits/interface/BTextView/InlineInput.cpp new file mode 100644 index 0000000000..68454002a2 --- /dev/null +++ b/src/kits/interface/BTextView/InlineInput.cpp @@ -0,0 +1,69 @@ +#include "InlineInput.h" + +#include + +_BInlineInput_::_BInlineInput_(BMessenger messenger) + : + fMessenger(messenger), + fActive(false), + fOffset(0), + fLength(0) +{ +} + + +_BInlineInput_::~_BInlineInput_() +{ +} + + +/*! \brief Returns a pointer to the Input Server Method BMessenger + which requested the transaction. +*/ +const BMessenger * +_BInlineInput_::Method() const +{ + return &fMessenger; +} + + +bool +_BInlineInput_::IsActive() const +{ + return fActive; +} + + +void +_BInlineInput_::SetActive(bool active) +{ + fActive = active; +} + + +int32 +_BInlineInput_::Length() const +{ + return fLength; +} + + +void +_BInlineInput_::SetLength(int32 len) +{ + fLength = len; +} + + +int32 +_BInlineInput_::Offset() const +{ + return fOffset; +} + + +void +_BInlineInput_::SetOffset(int32 offset) +{ + fOffset = offset; +} diff --git a/src/kits/interface/BTextView/InlineInput.h b/src/kits/interface/BTextView/InlineInput.h new file mode 100644 index 0000000000..31f1e1ba68 --- /dev/null +++ b/src/kits/interface/BTextView/InlineInput.h @@ -0,0 +1,31 @@ +#ifndef __INLINEINPUT_H +#define __INLINEINPUT_H + +#include + +class _BInlineInput_ { +public: + _BInlineInput_(BMessenger); + ~_BInlineInput_(); + + const BMessenger *Method() const; + + bool IsActive() const; + void SetActive(bool active); + + int32 Length() const; + void SetLength(int32 length); + + int32 Offset() const; + void SetOffset(int32 offset); + +private: + const BMessenger fMessenger; + + bool fActive; + + int32 fOffset; + int32 fLength; +}; + +#endif //__INLINEINPUT_H diff --git a/src/kits/interface/BTextView/Jamfile b/src/kits/interface/BTextView/Jamfile index cee59d3465..d3399ca9e2 100644 --- a/src/kits/interface/BTextView/Jamfile +++ b/src/kits/interface/BTextView/Jamfile @@ -3,6 +3,7 @@ SubDir OBOS_TOP src kits interface BTextView ; UsePrivateHeaders interface ; StaticLibrary haiku : + InlineInput.cpp LineBuffer.cpp StyleBuffer.cpp TextGapBuffer.cpp diff --git a/src/kits/interface/BTextView/StyleBuffer.cpp b/src/kits/interface/BTextView/StyleBuffer.cpp index b6e6b2ad9d..7274325601 100644 --- a/src/kits/interface/BTextView/StyleBuffer.cpp +++ b/src/kits/interface/BTextView/StyleBuffer.cpp @@ -27,6 +27,7 @@ // Standard Includes ----------------------------------------------------------- // System Includes ------------------------------------------------------------- +#include "InlineInput.h" #include "StyleBuffer.h" // Project Includes ------------------------------------------------------------ @@ -479,7 +480,7 @@ _BStyleBuffer_::RemoveStyles(int32 index, int32 count) } //------------------------------------------------------------------------------ int32 -_BStyleBuffer_::Iterate(int32 fromOffset, int32 length, /*_BInlineInput_ *,*/ +_BStyleBuffer_::Iterate(int32 fromOffset, int32 length, _BInlineInput_ *input, const BFont **outFont, const rgb_color **outColor, float *outAscent, float *outDescent, uint32 *) const { diff --git a/src/kits/interface/BTextView/StyleBuffer.h b/src/kits/interface/BTextView/StyleBuffer.h index 1eb9e0376f..4de7e04942 100644 --- a/src/kits/interface/BTextView/StyleBuffer.h +++ b/src/kits/interface/BTextView/StyleBuffer.h @@ -122,6 +122,7 @@ STEStyleRecordPtr _BStyleRecordBuffer_::operator[](int32 index) const } //------------------------------------------------------------------------------ +class _BInlineInput_; // _BStyleBuffer_ class -------------------------------------------------------- class _BStyleBuffer_ { @@ -150,7 +151,7 @@ public: void RemoveStyleRange(int32 fromOffset, int32 toOffset); void RemoveStyles(int32 index, int32 count = 1); - int32 Iterate(int32 fromOffset, int32 length, /*_BInlineInput_ *,*/ + int32 Iterate(int32 fromOffset, int32 length, _BInlineInput_ *, const BFont **outFont = NULL, const rgb_color **outColor = NULL, float *outAscent = NULL, diff --git a/src/kits/interface/BTextView/TextView.cpp b/src/kits/interface/BTextView/TextView.cpp index 6c039a5c4f..bbaadbc678 100644 --- a/src/kits/interface/BTextView/TextView.cpp +++ b/src/kits/interface/BTextView/TextView.cpp @@ -1,5 +1,5 @@ //------------------------------------------------------------------------------ -// Copyright (c) 2001-2004, Haiku +// Copyright (c) 2001-2004, Haiku, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -28,9 +28,9 @@ // TODO: // - Finish documenting this class -// - Consider using _PointerList_/BObjectList instead of BList +// - Consider using BObjectList instead of BList // for disallowed charachters (it would remove a lot of reinterpret_casts) - +// - Asynchronous mouse tracking // Standard Includes ----------------------------------------------------------- #include @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ #include // Local Includes -------------------------------------------------------------- +#include "InlineInput.h" #include "LineBuffer.h" #include "StyleBuffer.h" #include "TextGapBuffer.h" @@ -431,6 +433,8 @@ BTextView::MouseDown(BPoint where) if (!fEditable && !fSelectable) return; + CancelInputMethod(); + if (!IsFocus()) MakeFocus(); @@ -819,23 +823,27 @@ BTextView::MessageReceived(BMessage *message) switch (opcode) { case B_INPUT_METHOD_STARTED: { - printf("B_INPUT_METHOD_STARTED\n"); + BMessenger messenger; + if (message->FindMessenger("be:reply_to", &messenger) == B_OK) { + ASSERT(fInline == NULL); + fInline = new _BInlineInput_(messenger); + } + break; } case B_INPUT_METHOD_STOPPED: { - printf("B_INPUT_METHOD_STOPPED\n"); + delete fInline; + fInline = NULL; break; } case B_INPUT_METHOD_CHANGED: - printf("B_INPUT_METHOD_CHANGED\n"); HandleInputMethodChanged(message); break; case B_INPUT_METHOD_LOCATION_REQUEST: - printf("B_INPUT_METHOD_LOCATION_REQUEST\n"); HandleInputMethodLocationRequest(); break; @@ -969,6 +977,9 @@ void BTextView::SetText(const char *inText, const text_run_array *inRuns) { CALLED(); + + CancelInputMethod(); + // hide the caret/unhilite the selection if (fActive) { if (fSelStart != fSelEnd) @@ -1005,6 +1016,9 @@ BTextView::SetText(const char *inText, int32 inLength, const text_run_array *inRuns) { CALLED(); + + CancelInputMethod(); + // hide the caret/unhilite the selection if (fActive) { if (fSelStart != fSelEnd) @@ -1039,7 +1053,11 @@ BTextView::SetText(BFile *inFile, int32 inOffset, int32 inLength, const text_run_array *inRuns) { CALLED(); - // TODO: Should probably call _DoDeleteText() here + + CancelInputMethod(); + + // TODO: Should probably call _DoDeleteText() here, as the bebook + // says this function doesn't dall DeleteText() if (fText->Length() > 0) DeleteText(0, fText->Length()); @@ -1093,6 +1111,9 @@ BTextView::Insert(int32 startOffset, const char *inText, int32 inLength, const text_run_array *inRuns) { CALLED(); + + CancelInputMethod(); + // do we really need to do anything? if (inLength < 1) return; @@ -1139,6 +1160,9 @@ void BTextView::Delete() { CALLED(); + + CancelInputMethod(); + // anything to delete? if (fSelStart == fSelEnd) return; @@ -1230,8 +1254,7 @@ BTextView::TextLength() const CALLED(); return fText->Length(); } - - +//------------------------------------------------------------------------------ void BTextView::GetText(int32 offset, int32 length, char *buffer) const { @@ -1280,6 +1303,7 @@ void BTextView::GoToLine(int32 index) { CALLED(); + CancelInputMethod(); fSelStart = fSelEnd = OffsetAt(index); } @@ -1291,6 +1315,7 @@ void BTextView::Cut(BClipboard *clipboard) { CALLED(); + CancelInputMethod(); if (fUndo) { delete fUndo; fUndo = new _BCutUndoBuffer_(this); @@ -1307,6 +1332,9 @@ void BTextView::Copy(BClipboard *clipboard) { CALLED(); + + CancelInputMethod(); + BMessage *clip = NULL; if (clipboard->Lock()) { @@ -1337,6 +1365,8 @@ void BTextView::Paste(BClipboard *clipboard) { CALLED(); + CancelInputMethod(); + BMessage *clip = NULL; if (clipboard->Lock()) { @@ -1427,7 +1457,7 @@ BTextView::Select(int32 startOffset, int32 endOffset) // is the new selection any different from the current selection? if (startOffset == fSelStart && endOffset == fSelEnd) return; - + fStyles->InvalidateNullStyle(); // pin offsets at reasonable values @@ -1513,6 +1543,8 @@ BTextView::SetFontAndColor(const BFont *inFont, uint32 inMode, const rgb_color *inColor) { CALLED(); + CancelInputMethod(); + // hide the caret/unhilite the selection if (fActive) { if (fSelStart != fSelEnd) @@ -1619,6 +1651,9 @@ BTextView::SetRunArray(int32 startOffset, int32 endOffset, const text_run_array *inRuns) { CALLED(); + + CancelInputMethod(); + // pin offsets at reasonable values startOffset = (startOffset < 0) ? 0 : startOffset; endOffset = (endOffset < 0) ? 0 : endOffset; @@ -2187,11 +2222,12 @@ BTextView::MakeEditable(bool editable) fEditable = editable; - if (Window() != NULL) { - if (fActive) { - if (!fEditable && fCaretVisible) + if (Window() != NULL && fActive) { + if (!fEditable) { + if (fCaretVisible) InvertCaret(); - } + CancelInputMethod(); + } } } @@ -3101,7 +3137,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent, if (fromOffset >= limit) { // try to return valid height info anyway if (fStyles->NumRuns() > 0) - fStyles->Iterate(fromOffset, 1, NULL, NULL, outAscent, outDescent); + fStyles->Iterate(fromOffset, 1, fInline, NULL, NULL, outAscent, outDescent); else { if (fStyles->IsValidNullStyle()) { const BFont *font = NULL; @@ -3137,7 +3173,7 @@ BTextView::FindLineBreak(int32 fromOffset, float *outAscent, int32 length = offset; int32 startOffset = fromOffset; int32 numChars; - while ((numChars = fStyles->Iterate(startOffset, length, NULL, NULL, &ascent, &descent)) != 0) { + while ((numChars = fStyles->Iterate(startOffset, length, fInline, NULL, NULL, &ascent, &descent)) != 0) { *outAscent = max_c(ascent, *outAscent); *outDescent = max_c(descent, *outDescent); @@ -3290,7 +3326,7 @@ BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent, // iterate through the style runs const BFont *font = NULL; int32 numChars; - while ((numChars = fStyles->Iterate(fromOffset, length, &font, NULL, &ascent, &descent)) != 0) { + while ((numChars = fStyles->Iterate(fromOffset, length, fInline, &font, NULL, &ascent, &descent)) != 0) { maxAscent = max_c(ascent, maxAscent); maxDescent = max_c(descent, maxDescent); @@ -3408,7 +3444,7 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset, const BFont *font = NULL; const rgb_color *color = NULL; int32 numChars; - while ((numChars = fStyles->Iterate(offset, length, &font, &color)) != 0) { + while ((numChars = fStyles->Iterate(offset, length, fInline, &font, &color)) != 0) { SetFont(font); SetHighColor(*color); @@ -3795,6 +3831,8 @@ BTextView::Deactivate() CALLED(); fActive = false; + CancelInputMethod(); + if (fSelStart != fSelEnd) { if (fSelectable) Highlight(fSelStart, fSelEnd); @@ -3837,7 +3875,7 @@ uint32 BTextView::CharClassification(int32 offset) const { CALLED(); - // Should check against a list of character containing also + // Should check against a list of characters containing also // japanese word breakers switch (fText->RealCharAt(offset)) { case B_SPACE: @@ -4003,11 +4041,43 @@ void BTextView::HandleInputMethodChanged(BMessage *message) { CALLED(); - // TODO: Implement me if (!fInline) return; + + // TODO: Highlight in blue/red the various clauses - message->PrintToStream(); + const char *string = NULL; + if (message->FindString("be:string", &string) != B_OK || string == NULL) + return; + + be_app->ObscureCursor(); + + // Delete the previously inserted text (if any) + if (fInline->IsActive()) { + int32 oldOffset = fInline->Offset(); + DeleteText(oldOffset, oldOffset + fInline->Length()); + Select(oldOffset, oldOffset); + } + + int32 stringLen = strlen(string); + + fInline->SetOffset(fSelStart); + fInline->SetLength(stringLen); + + // Insert the new text + InsertText(string, stringLen, fSelStart, NULL); + Select(fSelStart + stringLen, fSelStart + stringLen); + + Refresh(0, fLines->NumLines(), true, false); + + // If we find the "be:confirmed" boolean (and the boolean is true), + // it means it's over for now, so the current _BInlineInput_ object + // should become inactive + bool confirmed = false; + if (message->FindBool("be:confirmed", &confirmed) != B_OK || !confirmed) + fInline->SetActive(true); + else + fInline->SetActive(false); } @@ -4019,15 +4089,45 @@ BTextView::HandleInputMethodLocationRequest() CALLED(); if (!fInline) return; - // TODO: Implement me + + int32 offset = fInline->Offset(); + int32 limit = offset + fInline->Length(); + + BMessage message(B_INPUT_METHOD_EVENT); + message.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST); + + // Add the location of the UTF8 charachters + float height = 0; + BPoint where; + while (offset < limit) { + where = PointAt(offset, &height); + ConvertToScreen(&where); + + message.AddPoint("be:location_reply", where); + message.AddFloat("be:height_reply", height); + + offset = NextInitialByte(offset); + } + + fInline->Method()->SendMessage(&message); } +/*! \brief Tells the input server method addon to stop the current transaction. +*/ void BTextView::CancelInputMethod() { - // TODO: Implement me CALLED(); + if (!fInline) + return; + + BMessage message(B_INPUT_METHOD_EVENT); + message.AddInt32("be:opcode", B_INPUT_METHOD_STOPPED); + fInline->Method()->SendMessage(&message); + + delete fInline; + fInline = NULL; }