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
15BlockListItem::BlockListItem(const char* label, uint32 blockIndex)
16	: BStringItem(label),
17	fBlockIndex(blockIndex)
18{
19}
20
21
22//	#pragma mark -
23
24
25UnicodeBlockView::UnicodeBlockView(const char* name)
26	: BListView(name),
27	fBlocks(kNumUnicodeBlocks, true),
28	fShowPrivateBlocks(false),
29	fShowContainedBlocksOnly(false)
30{
31	_CreateBlocks();
32}
33
34
35UnicodeBlockView::~UnicodeBlockView()
36{
37}
38
39
40void
41UnicodeBlockView::SetFilter(const char* filter)
42{
43	fFilter = filter;
44	_UpdateBlocks();
45}
46
47void
48UnicodeBlockView::SetCharacterFont(const BFont& font)
49{
50	fCharacterFont = font;
51	fUnicodeBlocks = fCharacterFont.Blocks();
52	_UpdateBlocks();
53}
54
55
56void
57UnicodeBlockView::ShowPrivateBlocks(bool show)
58{
59	if (fShowPrivateBlocks == show)
60		return;
61
62	fShowPrivateBlocks = show;
63	_UpdateBlocks();
64}
65
66
67void
68UnicodeBlockView::ShowContainedBlocksOnly(bool show)
69{
70	if (fShowContainedBlocksOnly == show)
71		return;
72
73	fShowContainedBlocksOnly = show;
74	_UpdateBlocks();
75}
76
77
78bool
79UnicodeBlockView::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
109void
110UnicodeBlockView::_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
127void
128UnicodeBlockView::_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
147void
148UnicodeBlockView::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