From 8f400a127ad8d2805104b69a279b4832a4bf42ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 2 Apr 2009 09:46:21 +0000 Subject: [PATCH] * Added filter control for the Unicode block list. * The status line now contains the character as well, as suggested by humdinger. * Moved the list view into its own class UnicodeBlockView. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29863 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/charactermap/CharacterWindow.cpp | 162 ++++++++++++++------- src/apps/charactermap/CharacterWindow.h | 9 +- src/apps/charactermap/Jamfile | 1 + src/apps/charactermap/UnicodeBlockView.cpp | 135 +++++++++++++++++ src/apps/charactermap/UnicodeBlockView.h | 59 ++++++++ src/apps/charactermap/UnicodeBlocks.cpp | 2 +- 6 files changed, 314 insertions(+), 54 deletions(-) create mode 100644 src/apps/charactermap/UnicodeBlockView.cpp create mode 100644 src/apps/charactermap/UnicodeBlockView.h diff --git a/src/apps/charactermap/CharacterWindow.cpp b/src/apps/charactermap/CharacterWindow.cpp index f4b862a311..b986ef4f77 100644 --- a/src/apps/charactermap/CharacterWindow.cpp +++ b/src/apps/charactermap/CharacterWindow.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -17,15 +18,17 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "CharacterView.h" -#include "UnicodeBlocks.h" +#include "UnicodeBlockView.h" static const uint32 kMsgUnicodeBlockSelected = 'unbs'; @@ -34,6 +37,9 @@ static const uint32 kMsgFontSelected = 'fnts'; static const uint32 kMsgFontSizeChanged = 'fsch'; static const uint32 kMsgPrivateBlocks = 'prbl'; static const uint32 kMsgContainedBlocks = 'cnbl'; +static const uint32 kMsgFilterChanged = 'fltr'; +static const uint32 kMsgFilterEntered = 'flte'; +static const uint32 kMsgClearFilter = 'clrf'; static const int32 kMinFontSize = 10; static const int32 kMaxFontSize = 72; @@ -59,6 +65,55 @@ private: mutable char fText[32]; }; +class MouseMovedFilter : public BMessageFilter { +public: + MouseMovedFilter() + : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, B_MOUSE_MOVED) + { + } + + int32 ResetMoved() + { + int32 old = fMouseMoved; + fMouseMoved = 0; + + return old; + } + + virtual filter_result Filter(BMessage* message, BHandler** /*_target*/) + { + fMouseMoved++; + return B_DISPATCH_MESSAGE; + } + +private: + int32 fMouseMoved; +}; + +class EscapeMessageFilter : public BMessageFilter { +public: + EscapeMessageFilter(uint32 command) + : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, B_KEY_DOWN), + fCommand(command) + { + } + + virtual filter_result Filter(BMessage* message, BHandler** /*_target*/) + { + const char* bytes; + if (message->what != B_KEY_DOWN + || message->FindString("bytes", &bytes) != B_OK + || bytes[0] != B_ESCAPE) + return B_DISPATCH_MESSAGE; + + Looper()->PostMessage(fCommand); + return B_SKIP_MESSAGE; + } + +private: + uint32 fCommand; +}; + CharacterWindow::CharacterWindow() : BWindow(BRect(100, 100, 700, 550), "CharacterMap", B_TITLED_WINDOW, @@ -80,7 +135,13 @@ CharacterWindow::CharacterWindow() BMenuBar* menuBar = new BMenuBar("menu"); - fUnicodeBlockView = new BListView("unicodeBlocks"); + fFilterControl = new BTextControl("Filter:", NULL, new BMessage(kMsgFilterEntered)); + fFilterControl->SetModificationMessage(new BMessage(kMsgFilterChanged)); + + BButton* clearButton = new BButton("clear", "Clear", + new BMessage(kMsgClearFilter)); + + fUnicodeBlockView = new UnicodeBlockView("unicodeBlocks"); fUnicodeBlockView->SetSelectionMessage( new BMessage(kMsgUnicodeBlockSelected)); @@ -90,11 +151,16 @@ CharacterWindow::CharacterWindow() fCharacterView = new CharacterView("characters"); fCharacterView->SetTarget(this, kMsgCharacterChanged); + // TODO: have a context object shared by CharacterView/UnicodeBlockView bool show; - if (settings.FindBool("show private blocks", &show) == B_OK) + if (settings.FindBool("show private blocks", &show) == B_OK) { fCharacterView->ShowPrivateBlocks(show); - if (settings.FindBool("show contained blocks only", &show) == B_OK) + fUnicodeBlockView->ShowPrivateBlocks(show); + } + if (settings.FindBool("show contained blocks only", &show) == B_OK) { fCharacterView->ShowContainedBlocksOnly(show); + fUnicodeBlockView->ShowPrivateBlocks(show); + } const char* family; const char* style; @@ -130,7 +196,11 @@ CharacterWindow::CharacterWindow() AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)//BSplitLayoutBuilder() - .Add(unicodeScroller) + .Add(BGroupLayoutBuilder(B_VERTICAL, 10) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10) + .Add(fFilterControl) + .Add(clearButton)) + .Add(unicodeScroller)) .Add(BGroupLayoutBuilder(B_VERTICAL, 10) .Add(characterScroller) .Add(fFontSizeSlider) @@ -167,8 +237,14 @@ CharacterWindow::CharacterWindow() menuBar->AddItem(_CreateFontMenu()); - _CreateUnicodeBlocks(); - InvalidateLayout(); + AddCommonFilter(new EscapeMessageFilter(kMsgClearFilter)); + fMouseMovedFilter = new MouseMovedFilter(); + AddCommonFilter(fMouseMovedFilter); + + // TODO: why is this needed? + fUnicodeBlockView->SetTarget(this); + + fFilterControl->MakeFocus(); } @@ -192,7 +268,13 @@ CharacterWindow::MessageReceived(BMessage* message) || index < 0) break; - fCharacterView->ScrollTo(index); + BlockListItem* item + = static_cast(fUnicodeBlockView->ItemAt(index)); + fCharacterView->ScrollTo(item->BlockIndex()); + + // Give the filter control focus if we got here by mouse action + if (fMouseMovedFilter->ResetMoved()) + fFilterControl->MakeFocus(); break; } @@ -202,13 +284,16 @@ CharacterWindow::MessageReceived(BMessage* message) if (message->FindInt32("character", (int32*)&character) != B_OK) break; + char utf8[16]; + CharacterView::UnicodeToUTF8(character, utf8, sizeof(utf8)); + char utf8Hex[32]; CharacterView::UnicodeToUTF8Hex(character, utf8Hex, sizeof(utf8Hex)); char text[128]; - snprintf(text, sizeof(text), "Code: %#lx (%ld), UTF-8: %s", - character, character, utf8Hex); + snprintf(text, sizeof(text), "'%s' Code: %#lx (%ld), UTF-8: %s", + utf8, character, character, utf8Hex); fCodeView->SetText(text); break; @@ -259,7 +344,7 @@ CharacterWindow::MessageReceived(BMessage* message) item->SetMarked(!item->IsMarked()); fCharacterView->ShowPrivateBlocks(item->IsMarked()); - _UpdateUnicodeBlocks(); + fUnicodeBlockView->ShowPrivateBlocks(item->IsMarked()); break; } @@ -273,10 +358,25 @@ CharacterWindow::MessageReceived(BMessage* message) item->SetMarked(!item->IsMarked()); fCharacterView->ShowContainedBlocksOnly(item->IsMarked()); - _UpdateUnicodeBlocks(); + fUnicodeBlockView->ShowContainedBlocksOnly(item->IsMarked()); break; } + case kMsgFilterChanged: + fUnicodeBlockView->SetFilter(fFilterControl->Text()); + break; + + case kMsgFilterEntered: + fUnicodeBlockView->MakeFocus(); + fUnicodeBlockView->Select(0); + fMouseMovedFilter->ResetMoved(); + break; + + case kMsgClearFilter: + fFilterControl->SetText(""); + fFilterControl->MakeFocus(); + break; + default: BWindow::MessageReceived(message); break; @@ -412,41 +512,3 @@ CharacterWindow::_CreateFontMenu() return menu; } - - -void -CharacterWindow::_UpdateUnicodeBlocks() -{ - for (int32 i = 0; i < fUnicodeBlockView->CountItems(); i++) { - BStringItem* item - = static_cast(fUnicodeBlockView->ItemAt(i)); - - bool enabled = fCharacterView->IsShowingBlock(i); - - if (item->IsEnabled() != enabled) { - item->SetEnabled(enabled); - fUnicodeBlockView->InvalidateItem(i); - } - } -} - - -void -CharacterWindow::_CreateUnicodeBlocks() -{ - float minWidth = 0; - for (uint32 i = 0; i < kNumUnicodeBlocks; i++) { - BStringItem* item = new BStringItem(kUnicodeBlocks[i].name); - fUnicodeBlockView->AddItem(item); - - float width = fUnicodeBlockView->StringWidth(item->Text()); - if (minWidth < width) - minWidth = width; - } - - fUnicodeBlockView->SetExplicitMinSize(BSize(minWidth / 2, 32)); - fUnicodeBlockView->SetExplicitMaxSize(BSize(minWidth, B_SIZE_UNSET)); - - _UpdateUnicodeBlocks(); -} - diff --git a/src/apps/charactermap/CharacterWindow.h b/src/apps/charactermap/CharacterWindow.h index a7a498b512..085d36fd4a 100644 --- a/src/apps/charactermap/CharacterWindow.h +++ b/src/apps/charactermap/CharacterWindow.h @@ -15,7 +15,10 @@ class BMenu; class BMenuItem; class BSlider; class BStringView; +class BTextControl; class CharacterView; +class MouseMovedFilter; +class UnicodeBlockView; class CharacterWindow : public BWindow { @@ -33,15 +36,15 @@ private: void _SetFont(const char* family, const char* style); BMenu* _CreateFontMenu(); - void _UpdateUnicodeBlocks(); - void _CreateUnicodeBlocks(); private: - BListView* fUnicodeBlockView; + BTextControl* fFilterControl; + UnicodeBlockView* fUnicodeBlockView; CharacterView* fCharacterView; BMenuItem* fSelectedFontItem; BSlider* fFontSizeSlider; BStringView* fCodeView; + MouseMovedFilter* fMouseMovedFilter; }; #endif // CHARACTER_WINDOW_H diff --git a/src/apps/charactermap/Jamfile b/src/apps/charactermap/Jamfile index 7625633fa2..b0ea13f2ae 100644 --- a/src/apps/charactermap/Jamfile +++ b/src/apps/charactermap/Jamfile @@ -9,6 +9,7 @@ Application CharacterMap : CharacterView.cpp CharacterWindow.cpp UnicodeBlocks.cpp + UnicodeBlockView.cpp : be : CharacterMap.rdef diff --git a/src/apps/charactermap/UnicodeBlockView.cpp b/src/apps/charactermap/UnicodeBlockView.cpp new file mode 100644 index 0000000000..9f6e75c1d3 --- /dev/null +++ b/src/apps/charactermap/UnicodeBlockView.cpp @@ -0,0 +1,135 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include "UnicodeBlockView.h" + +#include +#include + +#include "UnicodeBlocks.h" + + +BlockListItem::BlockListItem(const char* label, uint32 blockIndex) + : BStringItem(label), + fBlockIndex(blockIndex) +{ +} + + +// #pragma mark - + + +UnicodeBlockView::UnicodeBlockView(const char* name) + : BListView(name), + fBlocks(kNumUnicodeBlocks, true), + fShowPrivateBlocks(false), + fShowContainedBlocksOnly(false) +{ +} + + +UnicodeBlockView::~UnicodeBlockView() +{ +} + + +void +UnicodeBlockView::SetFilter(const char* filter) +{ + fFilter = filter; + _UpdateBlocks(); +} + + +void +UnicodeBlockView::ShowPrivateBlocks(bool show) +{ + if (fShowPrivateBlocks == show) + return; + + fShowPrivateBlocks = show; + _UpdateBlocks(); +} + + +void +UnicodeBlockView::ShowContainedBlocksOnly(bool show) +{ + if (fShowContainedBlocksOnly == show) + return; + + fShowContainedBlocksOnly = show; + _UpdateBlocks(); +} + + +bool +UnicodeBlockView::IsShowingBlock(int32 blockIndex) const +{ + if (blockIndex < 0 || blockIndex >= (int32)kNumUnicodeBlocks) + return false; + + if (!fShowPrivateBlocks && kUnicodeBlocks[blockIndex].private_block) + return false; + + return true; +} + + +void +UnicodeBlockView::AttachedToWindow() +{ + // TODO: if we're calling this in the constructor, strange things happen + _CreateBlocks(); +} + + +void +UnicodeBlockView::DetachedFromWindow() +{ + MakeEmpty(); + fBlocks.MakeEmpty(); +} + + +void +UnicodeBlockView::_UpdateBlocks() +{ + MakeEmpty(); + + for (int32 i = 0; i < fBlocks.CountItems(); i++) { + if (fFilter.Length() != 0) { + if (strcasestr(kUnicodeBlocks[i].name, fFilter.String()) == NULL) + continue; + } + + if (!IsShowingBlock(i)) + continue; + + AddItem(fBlocks.ItemAt(i)); + } +} + + +void +UnicodeBlockView::_CreateBlocks() +{ + float minWidth = 0; + for (uint32 i = 0; i < kNumUnicodeBlocks; i++) { + BlockListItem* item = new BlockListItem(kUnicodeBlocks[i].name, i); + fBlocks.AddItem(item); + + float width = StringWidth(item->Text()); + if (minWidth < width) + minWidth = width; + } + + SetExplicitMinSize(BSize(minWidth / 2, 32)); + SetExplicitMaxSize(BSize(minWidth, B_SIZE_UNSET)); + + _UpdateBlocks(); +} + diff --git a/src/apps/charactermap/UnicodeBlockView.h b/src/apps/charactermap/UnicodeBlockView.h new file mode 100644 index 0000000000..cb6f59273c --- /dev/null +++ b/src/apps/charactermap/UnicodeBlockView.h @@ -0,0 +1,59 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef UNICODE_BLOCK_VIEW_H +#define UNICODE_BLOCK_VIEW_H + + +#include +#include +#include + + +class BlockListItem : public BStringItem { +public: + BlockListItem(const char* label, uint32 blockIndex); + + uint32 BlockIndex() const { return fBlockIndex; } + +private: + uint32 fBlockIndex; +}; + + +class UnicodeBlockView : public BListView { +public: + UnicodeBlockView(const char* name); + virtual ~UnicodeBlockView(); + + void SetFilter(const char* filter); + const char* Filter() const + { return fFilter.String(); } + + void ShowPrivateBlocks(bool show); + bool IsShowingPrivateBlocks() const + { return fShowPrivateBlocks; } + + void ShowContainedBlocksOnly(bool show); + bool IsShowingContainedBlocksOnly() const + { return fShowContainedBlocksOnly; } + + bool IsShowingBlock(int32 blockIndex) const; + +protected: + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + +private: + void _UpdateBlocks(); + void _CreateBlocks(); + +private: + BObjectList fBlocks; + BString fFilter; + bool fShowPrivateBlocks; + bool fShowContainedBlocksOnly; +}; + +#endif // UNICODE_BLOCK_VIEW_H diff --git a/src/apps/charactermap/UnicodeBlocks.cpp b/src/apps/charactermap/UnicodeBlocks.cpp index 0836ded89a..f2d492e87f 100644 --- a/src/apps/charactermap/UnicodeBlocks.cpp +++ b/src/apps/charactermap/UnicodeBlocks.cpp @@ -130,7 +130,7 @@ const struct unicode_block_entry kUnicodeBlocks[] = { {"Vai", 0xa500, 0xa63f, false, kNoBlock}, {"Cyrillic Extended B", 0xa640, 0xa69f, false, kNoBlock}, {"Modifier Tone Letters", 0xa700, 0xa71f, false, kNoBlock}, - {"Lating Extended D", 0xa720, 0xa7ff, false, kNoBlock}, + {"Latin Extended D", 0xa720, 0xa7ff, false, kNoBlock}, {"Syloti Nagri", 0xa800, 0xa82f, false, kNoBlock}, {"Phags-pa", 0xa840, 0xa87f, false, kNoBlock}, {"Saurashtra", 0xa880, 0xa8df, false, kNoBlock},