xref: /haiku/src/apps/charactermap/UnicodeBlockView.cpp (revision a127b88ecbfab58f64944c98aa47722a18e363b2)
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 
15 BlockListItem::BlockListItem(const char* label, uint32 blockIndex)
16 	: BStringItem(label),
17 	fBlockIndex(blockIndex)
18 {
19 }
20 
21 
22 //	#pragma mark -
23 
24 
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 
35 UnicodeBlockView::~UnicodeBlockView()
36 {
37 }
38 
39 
40 void
41 UnicodeBlockView::SetFilter(const char* filter)
42 {
43 	fFilter = filter;
44 	_UpdateBlocks();
45 }
46 
47 void
48 UnicodeBlockView::SetCharacterFont(const BFont& font)
49 {
50 	fCharacterFont = font;
51 	fUnicodeBlocks = fCharacterFont.Blocks();
52 	_UpdateBlocks();
53 }
54 
55 
56 void
57 UnicodeBlockView::ShowPrivateBlocks(bool show)
58 {
59 	if (fShowPrivateBlocks == show)
60 		return;
61 
62 	fShowPrivateBlocks = show;
63 	_UpdateBlocks();
64 }
65 
66 
67 void
68 UnicodeBlockView::ShowContainedBlocksOnly(bool show)
69 {
70 	if (fShowContainedBlocksOnly == show)
71 		return;
72 
73 	fShowContainedBlocksOnly = show;
74 	_UpdateBlocks();
75 }
76 
77 
78 bool
79 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 Includes method checks for unicode blocks as
89 	// defined by Be, 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 			&& !fUnicodeBlocks.Includes(
96 				kUnicodeBlocks[blockIndex].block))
97 			return false;
98 
99 		if (!fCharacterFont.IncludesBlock(
100 				kUnicodeBlocks[blockIndex].start,
101 				kUnicodeBlocks[blockIndex].end))
102 			return false;
103 	}
104 
105 	return true;
106 }
107 
108 
109 void
110 UnicodeBlockView::_UpdateBlocks()
111 {
112 	MakeEmpty();
113 
114 	for (int32 i = 0; i < fBlocks.CountItems(); i++) {
115 		if (fFilter.Length() != 0) {
116 			if (strcasestr(kUnicodeBlocks[i].name, fFilter.String()) == NULL)
117 				continue;
118 		}
119 
120 		AddItem(fBlocks.ItemAt(i));
121 
122 		fBlocks.ItemAt(i)->SetEnabled(IsShowingBlock(i));
123 	}
124 }
125 
126 
127 void
128 UnicodeBlockView::_CreateBlocks()
129 {
130 	float minWidth = 0;
131 	for (uint32 i = 0; i < kNumUnicodeBlocks; i++) {
132 		BlockListItem* item = new BlockListItem(kUnicodeBlocks[i].name, i);
133 		fBlocks.AddItem(item);
134 
135 		float width = StringWidth(item->Text());
136 		if (minWidth < width)
137 			minWidth = width;
138 	}
139 
140 	SetExplicitMinSize(BSize(minWidth / 2, 32));
141 	SetExplicitMaxSize(BSize(minWidth, B_SIZE_UNSET));
142 
143 	_UpdateBlocks();
144 }
145 
146 
147 void
148 UnicodeBlockView::SelectBlockForCharacter(uint32 character)
149 {
150 	// find block containing the character
151 	int32 blockNumber = BlockForCharacter(character);
152 
153 	if (blockNumber > 0) {
154 		BlockListItem* block = fBlocks.ItemAt(blockNumber);
155 
156 		int32 blockIndex = IndexOf(block);
157 
158 		if (blockIndex >= 0) {
159 			Select(blockIndex);
160 			ScrollToSelection();
161 		}
162 	}
163 }
164