1 /*
2 * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "UnicodeBlockView.h"
8
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "UnicodeBlocks.h"
13
14
BlockListItem(const char * label,uint32 blockIndex)15 BlockListItem::BlockListItem(const char* label, uint32 blockIndex)
16 : BStringItem(label),
17 fBlockIndex(blockIndex)
18 {
19 }
20
21
22 // #pragma mark -
23
24
UnicodeBlockView(const char * name)25 UnicodeBlockView::UnicodeBlockView(const char* name)
26 : BListView(name),
27 fBlocks(kNumUnicodeBlocks, true),
28 fShowPrivateBlocks(false),
29 fShowContainedBlocksOnly(false)
30 {
31 _CreateBlocks();
32 }
33
34
~UnicodeBlockView()35 UnicodeBlockView::~UnicodeBlockView()
36 {
37 }
38
39
40 void
SetFilter(const char * filter)41 UnicodeBlockView::SetFilter(const char* filter)
42 {
43 fFilter = filter;
44 _UpdateBlocks();
45 }
46
47 void
SetCharacterFont(const BFont & font)48 UnicodeBlockView::SetCharacterFont(const BFont& font)
49 {
50 fCharacterFont = font;
51 fUnicodeBlocks = fCharacterFont.Blocks();
52 _UpdateBlocks();
53 }
54
55
56 void
ShowPrivateBlocks(bool show)57 UnicodeBlockView::ShowPrivateBlocks(bool show)
58 {
59 if (fShowPrivateBlocks == show)
60 return;
61
62 fShowPrivateBlocks = show;
63 _UpdateBlocks();
64 }
65
66
67 void
ShowContainedBlocksOnly(bool show)68 UnicodeBlockView::ShowContainedBlocksOnly(bool show)
69 {
70 if (fShowContainedBlocksOnly == show)
71 return;
72
73 fShowContainedBlocksOnly = show;
74 _UpdateBlocks();
75 }
76
77
78 bool
IsShowingBlock(int32 blockIndex) const79 UnicodeBlockView::IsShowingBlock(int32 blockIndex) const
80 {
81 if (blockIndex < 0 || blockIndex >= (int32)kNumUnicodeBlocks)
82 return false;
83
84 if (!fShowPrivateBlocks && kUnicodeBlocks[blockIndex].private_block)
85 return false;
86
87 // The reason for two checks is BeOS compatibility.
88 // The first one checks for unicode blocks as defined by Be,
89 // but there are only 71 such blocks.
90 // The rest of the blocks (denoted by kNoBlock) need to
91 // be queried by searching for the start and end codepoints
92 // via the IncludesBlock method.
93 if (fShowContainedBlocksOnly) {
94 if (kUnicodeBlocks[blockIndex].block != kNoBlock)
95 return (fUnicodeBlocks & kUnicodeBlocks[blockIndex].block) != kNoBlock;
96
97 if (!fCharacterFont.IncludesBlock(
98 kUnicodeBlocks[blockIndex].start,
99 kUnicodeBlocks[blockIndex].end))
100 return false;
101 }
102
103 return true;
104 }
105
106
107 void
_UpdateBlocks()108 UnicodeBlockView::_UpdateBlocks()
109 {
110 MakeEmpty();
111
112 for (int32 i = 0; i < fBlocks.CountItems(); i++) {
113 if (fFilter.Length() != 0) {
114 if (strcasestr(kUnicodeBlocks[i].name, fFilter.String()) == NULL)
115 continue;
116 }
117
118 AddItem(fBlocks.ItemAt(i));
119
120 fBlocks.ItemAt(i)->SetEnabled(IsShowingBlock(i));
121 }
122 }
123
124
125 void
_CreateBlocks()126 UnicodeBlockView::_CreateBlocks()
127 {
128 float minWidth = 0;
129 for (uint32 i = 0; i < kNumUnicodeBlocks; i++) {
130 BlockListItem* item = new BlockListItem(kUnicodeBlocks[i].name, i);
131 fBlocks.AddItem(item);
132
133 float width = StringWidth(item->Text());
134 if (minWidth < width)
135 minWidth = width;
136 }
137
138 SetExplicitMinSize(BSize(minWidth / 2, 32));
139 SetExplicitMaxSize(BSize(minWidth, B_SIZE_UNSET));
140
141 _UpdateBlocks();
142 }
143
144
145 void
SelectBlockForCharacter(uint32 character)146 UnicodeBlockView::SelectBlockForCharacter(uint32 character)
147 {
148 // find block containing the character
149 int32 blockNumber = BlockForCharacter(character);
150
151 if (blockNumber > 0) {
152 BlockListItem* block = fBlocks.ItemAt(blockNumber);
153
154 int32 blockIndex = IndexOf(block);
155
156 if (blockIndex >= 0) {
157 Select(blockIndex);
158 ScrollToSelection();
159 }
160 }
161 }
162