From 498c03bdd66b5e3252023b6d94a251160ec61120 Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Fri, 14 Aug 2009 22:44:44 +0000 Subject: [PATCH] StringEditor : The TextView wasn't sending messages saying its content was modified by the user. Symptoms : * The Save menu item wasn't enabled * the undo/redo menu item weren't neither The fix I made was to commit the changes made by the user to the editor instance, by augmenting the InsertText and DeleteText from the TextView. This fixes ticket #3507. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32402 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/diskprobe/DataEditor.cpp | 9 +-- src/apps/diskprobe/DataEditor.h | 5 +- src/apps/diskprobe/TypeEditors.cpp | 98 +++++++++++++++++++++++++----- src/apps/diskprobe/TypeEditors.h | 2 +- 4 files changed, 91 insertions(+), 23 deletions(-) diff --git a/src/apps/diskprobe/DataEditor.cpp b/src/apps/diskprobe/DataEditor.cpp index 2fd85a28df..71cb058730 100644 --- a/src/apps/diskprobe/DataEditor.cpp +++ b/src/apps/diskprobe/DataEditor.cpp @@ -526,7 +526,7 @@ DataEditor::InitCheck() void -DataEditor::AddChange(DataChange *change) +DataEditor::AddChange(DataChange *change, bool sendNotices) { if (change == NULL) return; @@ -537,7 +537,8 @@ DataEditor::AddChange(DataChange *change) RemoveRedos(); change->Apply(fRealViewOffset, fView, fRealViewSize); - SendNotices(change); + if (sendNotices) + SendNotices(change); // update observers // try to join changes @@ -551,7 +552,7 @@ DataEditor::AddChange(DataChange *change) status_t -DataEditor::Replace(off_t offset, const uint8 *data, size_t length) +DataEditor::Replace(off_t offset, const uint8 *data, size_t length, bool sendNotices) { if (IsReadOnly()) return B_NOT_ALLOWED; @@ -570,7 +571,7 @@ DataEditor::Replace(off_t offset, const uint8 *data, size_t length) } ReplaceChange *change = new ReplaceChange(offset, data, length); - AddChange(change); + AddChange(change, sendNotices); return B_OK; } diff --git a/src/apps/diskprobe/DataEditor.h b/src/apps/diskprobe/DataEditor.h index 1d0ef7c9c6..2e0ba6feec 100644 --- a/src/apps/diskprobe/DataEditor.h +++ b/src/apps/diskprobe/DataEditor.h @@ -44,7 +44,8 @@ class DataEditor : public BLocker { status_t InitCheck(); - status_t Replace(off_t offset, const uint8 *data, size_t length); + status_t Replace(off_t offset, const uint8 *data, size_t length, + bool sendNotices = true); status_t Remove(off_t offset, off_t length); status_t Insert(off_t offset, const uint8 *data, size_t length); @@ -94,7 +95,7 @@ class DataEditor : public BLocker { void SendNotices(uint32 what, BMessage *message = NULL); void SendNotices(DataChange *change); status_t Update(); - void AddChange(DataChange *change); + void AddChange(DataChange *change, bool sendNotices = true); void ApplyChanges(); void RemoveRedos(); diff --git a/src/apps/diskprobe/TypeEditors.cpp b/src/apps/diskprobe/TypeEditors.cpp index f98b42ce57..40dfd1cee5 100644 --- a/src/apps/diskprobe/TypeEditors.cpp +++ b/src/apps/diskprobe/TypeEditors.cpp @@ -36,6 +36,24 @@ static const uint32 kMsgScaleChanged = 'scch'; static const uint32 kMimeTypeItem = 'miti'; +class StringEditorTextView : public BTextView { + public: + StringEditorTextView(BRect rect, TypeEditorView* target); + + bool fCommit; + + protected: + virtual void InsertText(const char* text, + int32 length, int32 offset, + const text_run_array* runs = NULL); + + virtual void DeleteText(int32 start, int32 finish); + + private: + TypeEditorView* fTarget; +}; + + class StringEditor : public TypeEditorView { public: StringEditor(BRect rect, DataEditor& editor); @@ -44,13 +62,13 @@ class StringEditor : public TypeEditorView { virtual void DetachedFromWindow(); virtual void MessageReceived(BMessage* message); - virtual void CommitChanges(); + virtual void CommitChanges(bool sendNotices = true); private: void _UpdateText(); - BTextView* fTextView; - BString fPreviousText; + StringEditorTextView* fTextView; + BString fPreviousText; }; @@ -62,7 +80,7 @@ class MimeTypeEditor : public TypeEditorView { virtual void DetachedFromWindow(); virtual void MessageReceived(BMessage* message); - virtual void CommitChanges(); + virtual void CommitChanges(bool sendNotices = true); virtual bool TypeMatches(); private: @@ -81,7 +99,7 @@ class NumberEditor : public TypeEditorView { virtual void DetachedFromWindow(); virtual void MessageReceived(BMessage* message); - virtual void CommitChanges(); + virtual void CommitChanges(bool sendNotices = true); virtual bool TypeMatches(); private: @@ -103,7 +121,7 @@ class BooleanEditor : public TypeEditorView { virtual void DetachedFromWindow(); virtual void MessageReceived(BMessage* message); - virtual void CommitChanges(); + virtual void CommitChanges(bool sendNotices = true); virtual bool TypeMatches(); private: @@ -169,7 +187,7 @@ TypeEditorView::~TypeEditorView() void -TypeEditorView::CommitChanges() +TypeEditorView::CommitChanges(bool sendNotices) { // the default just does nothing here } @@ -197,6 +215,7 @@ StringEditor::StringEditor(BRect rect, DataEditor& editor) BStringView *stringView = new BStringView(BRect(5, 5, rect.right, 20), B_EMPTY_STRING, "Contents:"); + stringView->ResizeToPreferred(); AddChild(stringView); @@ -205,9 +224,7 @@ StringEditor::StringEditor(BRect rect, DataEditor& editor) rect.right -= B_V_SCROLL_BAR_WIDTH; rect.bottom -= B_H_SCROLL_BAR_HEIGHT; - fTextView = new BTextView(rect, B_EMPTY_STRING, - rect.OffsetToCopy(B_ORIGIN).InsetByCopy(5, 5), - B_FOLLOW_ALL, B_WILL_DRAW); + fTextView = new StringEditorTextView(rect, this); BScrollView* scrollView = new BScrollView("scroller", fTextView, B_FOLLOW_ALL, B_WILL_DRAW, true, true); @@ -215,6 +232,43 @@ StringEditor::StringEditor(BRect rect, DataEditor& editor) } +/* + * fCommit is true if (Insert/Delete)Text is called from interaction with the user + * (text typed..) + * It's false if it's called from _UpdateText(); + * This is to avoid a SetText feedback loop + * CommitChanges -> UpdateText -> SetText -> InsertText -> CommitChanges... + */ +StringEditorTextView::StringEditorTextView(BRect rect, TypeEditorView* target) + : + BTextView(rect, B_EMPTY_STRING, + rect.OffsetToCopy(B_ORIGIN).InsetByCopy(5, 5), + B_FOLLOW_ALL, B_WILL_DRAW), + fCommit(true), + fTarget(target) +{ +} + + +void +StringEditorTextView::InsertText(const char* text, + int32 length, int32 offset, const text_run_array* runs) +{ + BTextView::InsertText(text, length, offset, runs); + if (fCommit) + fTarget->CommitChanges(false); +} + + +void +StringEditorTextView::DeleteText(int32 start, int32 finish) +{ + BTextView::DeleteText(start, finish); + if (fCommit) + fTarget->CommitChanges(false); +} + + void StringEditor::_UpdateText() { @@ -227,7 +281,9 @@ StringEditor::_UpdateText() const char *buffer; if (fEditor.GetViewBuffer((const uint8 **)&buffer) == B_OK) { + fTextView->fCommit = false; fTextView->SetText(buffer); + fTextView->fCommit = true; fPreviousText.SetTo(buffer); } @@ -237,11 +293,11 @@ StringEditor::_UpdateText() void -StringEditor::CommitChanges() +StringEditor::CommitChanges(bool sendNotices) { if (fPreviousText != fTextView->Text()) { fEditor.Replace(0, (const uint8 *)fTextView->Text(), - fTextView->TextLength() + 1); + fTextView->TextLength() + 1, sendNotices); } } @@ -267,7 +323,17 @@ StringEditor::DetachedFromWindow() void StringEditor::MessageReceived(BMessage *message) { - BView::MessageReceived(message); + switch (message->what) { + case kMsgValueChanged: + CommitChanges(); + break; + case kMsgDataEditorUpdate: + _UpdateText(); + break; + + default: + BView::MessageReceived(message); + } } @@ -307,7 +373,7 @@ MimeTypeEditor::_UpdateText() void -MimeTypeEditor::CommitChanges() +MimeTypeEditor::CommitChanges(bool sendNotices) { if (fPreviousText != fTextControl->Text()) { fEditor.Replace(0, (const uint8*)fTextControl->Text(), @@ -488,7 +554,7 @@ NumberEditor::TypeMatches() void -NumberEditor::CommitChanges() +NumberEditor::CommitChanges(bool sendNotices) { if (fPreviousText == fTextControl->Text()) return; @@ -792,7 +858,7 @@ BooleanEditor::_UpdateMenuField() void -BooleanEditor::CommitChanges() +BooleanEditor::CommitChanges(bool sendNotices) { // we're commiting the changes as they happen } diff --git a/src/apps/diskprobe/TypeEditors.h b/src/apps/diskprobe/TypeEditors.h index 8b0c3dbe8a..dd0286e9c9 100644 --- a/src/apps/diskprobe/TypeEditors.h +++ b/src/apps/diskprobe/TypeEditors.h @@ -17,7 +17,7 @@ class TypeEditorView : public BView { uint32 flags, DataEditor& editor); ~TypeEditorView(); - virtual void CommitChanges(); + virtual void CommitChanges(bool sendNotices = true); virtual bool TypeMatches(); protected: