* 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
This commit is contained in:
Axel Dörfler 2009-04-02 09:46:21 +00:00
parent cdc7175bfd
commit 8f400a127a
6 changed files with 314 additions and 54 deletions

View File

@ -10,6 +10,7 @@
#include <string.h>
#include <Application.h>
#include <Button.h>
#include <File.h>
#include <FindDirectory.h>
#include <GroupLayoutBuilder.h>
@ -17,15 +18,17 @@
#include <Menu.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <MessageFilter.h>
#include <Path.h>
#include <Roster.h>
#include <ScrollView.h>
#include <Slider.h>
#include <SplitLayoutBuilder.h>
#include <StringView.h>
#include <TextControl.h>
#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<BlockListItem*>(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<BStringItem*>(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();
}

View File

@ -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

View File

@ -9,6 +9,7 @@ Application CharacterMap :
CharacterView.cpp
CharacterWindow.cpp
UnicodeBlocks.cpp
UnicodeBlockView.cpp
: be
: CharacterMap.rdef

View File

@ -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 <stdio.h>
#include <string.h>
#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();
}

View File

@ -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 <ListView.h>
#include <ObjectList.h>
#include <String.h>
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<BlockListItem> fBlocks;
BString fFilter;
bool fShowPrivateBlocks;
bool fShowContainedBlocksOnly;
};
#endif // UNICODE_BLOCK_VIEW_H

View File

@ -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},