LibreOffice Module svx (master) 1
searchcharmap.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <config_wasm_strip.h>
21
22#include <vcl/event.hxx>
23#include <vcl/svapp.hxx>
24#include <vcl/settings.hxx>
25#include <vcl/virdev.hxx>
26
27#include <svx/ucsubset.hxx>
28#include <unordered_map>
29
30#include <svx/searchcharmap.hxx>
31
32#include <charmapacc.hxx>
33
34#include <rtl/ustrbuf.hxx>
35
36using namespace ::com::sun::star::accessibility;
37using namespace ::com::sun::star::uno;
38using namespace ::com::sun::star;
39
40
41SvxSearchCharSet::SvxSearchCharSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow, const VclPtr<VirtualDevice>& rVirDev)
42 : SvxShowCharSet(std::move(pScrolledWindow), rVirDev)
43 , nCount(0)
44{
45}
46
48{
49 int nIndex = FirstInView();
51 int nCompare = nCount - 1;
52 if (nIndex > nCompare)
53 nIndex = nCompare;
54 return nIndex;
55}
56
58{
59 vcl::KeyCode aCode = rKEvt.GetKeyCode();
60
61 if (aCode.GetModifier())
62 return false;
63
64 int tmpSelected = nSelectedIndex;
65
66 bool bRet = true;
67
68 switch (aCode.GetCode())
69 {
70 case KEY_SPACE:
71 aSelectHdl.Call( this );
72 break;
73 case KEY_LEFT:
74 --tmpSelected;
75 break;
76 case KEY_RIGHT:
77 ++tmpSelected;
78 break;
79 case KEY_UP:
80 tmpSelected -= COLUMN_COUNT;
81 break;
82 case KEY_DOWN:
83 tmpSelected += COLUMN_COUNT;
84 break;
85 case KEY_PAGEUP:
86 tmpSelected -= ROW_COUNT * COLUMN_COUNT;
87 break;
88 case KEY_PAGEDOWN:
89 tmpSelected += ROW_COUNT * COLUMN_COUNT;
90 break;
91 case KEY_HOME:
92 tmpSelected = 0;
93 break;
94 case KEY_END:
95 tmpSelected = nCount - 1;
96 break;
97 case KEY_TAB: // some fonts have a character at these unicode control codes
98 case KEY_ESCAPE:
99 case KEY_RETURN:
100 bRet = false;
101 tmpSelected = - 1; // mark as invalid
102 break;
103 default:
104 tmpSelected = -1;
105 bRet = false;
106 break;
107 }
108
109 if ( tmpSelected >= 0 )
110 {
111 SelectIndex( tmpSelected, true );
112 aPreSelectHdl.Call( this );
113 }
114
115 return bRet;
116}
117
119{
120 if (!mxFontCharMap.is())
122
123 // get next available char of current font
124 sal_UCS4 cChar = sub->GetRangeMin();
125 int nMapIndex = 0;
126
127 while(cChar <= sub->GetRangeMax() && nMapIndex == 0)
128 {
129 auto it = std::find_if(m_aItemList.begin(), m_aItemList.end(),
130 [&cChar](const std::pair<const sal_Int32, sal_UCS4>& rItem) { return rItem.second == cChar; });
131 if (it != m_aItemList.end())
132 nMapIndex = it->first;
133 cChar++;
134 }
135
136 if(nMapIndex == 0)
137 SelectIndex( 0 );
138 else
139 SelectIndex( nMapIndex );
140 aHighHdl.Call(this);
141 // move selected item to top row if not in focus
142 //TO.DO aVscrollSB->SetThumbPos( nMapIndex / COLUMN_COUNT );
143 Invalidate();
144}
145
147{
148 InitSettings(rRenderContext);
149 RecalculateFont(rRenderContext);
150 DrawChars_Impl(rRenderContext, FirstInView(), LastInView());
151}
152
153void SvxSearchCharSet::DrawChars_Impl(vcl::RenderContext& rRenderContext, int n1, int n2)
154{
155 if (n1 > LastInView() || n2 < FirstInView())
156 return;
157
158 Size aOutputSize(GetOutputSizePixel());
159
160 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
161 const Color aWindowTextColor(rStyleSettings.GetFieldTextColor());
162 Color aHighlightColor(rStyleSettings.GetHighlightColor());
163 Color aHighlightTextColor(rStyleSettings.GetHighlightTextColor());
164 Color aFaceColor(rStyleSettings.GetFaceColor());
165 Color aLightColor(rStyleSettings.GetLightColor());
166 Color aShadowColor(rStyleSettings.GetShadowColor());
167
168 int i;
169 rRenderContext.SetLineColor(aShadowColor);
170 for (i = 1; i < COLUMN_COUNT; ++i)
171 {
172 rRenderContext.DrawLine(Point(nX * i + m_nXGap, 0),
173 Point(nX * i + m_nXGap, aOutputSize.Height()));
174 }
175 for (i = 1; i < ROW_COUNT; ++i)
176 {
177 rRenderContext.DrawLine(Point(0, nY * i + m_nYGap),
178 Point(aOutputSize.Width(), nY * i + m_nYGap));
179 }
180
181 int nTextHeight = rRenderContext.GetTextHeight();
182 tools::Rectangle aBoundRect;
183 for (i = n1; i <= n2; ++i)
184 {
185 Point pix = MapIndexToPixel(i);
186 int x = pix.X();
187 int y = pix.Y();
188
189 OUStringBuffer buf;
190 std::unordered_map<sal_Int32, sal_UCS4>::const_iterator got = m_aItemList.find (i);
192
193 if(got == m_aItemList.end())
194 continue;
195 else
196 sName = got->second;
197
198 buf.appendUtf32(sName);
199 OUString aCharStr(buf.makeStringAndClear());
200 int nTextWidth = rRenderContext.GetTextWidth(aCharStr);
201 int tx = x + (nX - nTextWidth + 1) / 2;
202 int ty = y + (nY - nTextHeight + 1) / 2;
203 Point aPointTxTy(tx, ty);
204
205 // adjust position before it gets out of bounds
206 if (rRenderContext.GetTextBoundRect(aBoundRect, aCharStr) && !aBoundRect.IsEmpty())
207 {
208 // zero advance width => use ink width to center glyph
209 if (!nTextWidth)
210 {
211 aPointTxTy.setX( x - aBoundRect.Left() + (nX - aBoundRect.GetWidth() + 1) / 2 );
212 }
213
214 aBoundRect += aPointTxTy;
215
216 // shift back vertically if needed
217 int nYLDelta = aBoundRect.Top() - y;
218 int nYHDelta = (y + nY) - aBoundRect.Bottom();
219 if (nYLDelta <= 0)
220 aPointTxTy.AdjustY( -(nYLDelta - 1) );
221 else if (nYHDelta <= 0)
222 aPointTxTy.AdjustY(nYHDelta - 1 );
223
224 // shift back horizontally if needed
225 int nXLDelta = aBoundRect.Left() - x;
226 int nXHDelta = (x + nX) - aBoundRect.Right();
227 if (nXLDelta <= 0)
228 aPointTxTy.AdjustX( -(nXLDelta - 1) );
229 else if (nXHDelta <= 0)
230 aPointTxTy.AdjustX(nXHDelta - 1 );
231 }
232
233 Color aTextCol = rRenderContext.GetTextColor();
234 if (i != nSelectedIndex)
235 {
236 rRenderContext.SetTextColor(aWindowTextColor);
237 rRenderContext.DrawText(aPointTxTy, aCharStr);
238 }
239 else
240 {
241 Color aLineCol = rRenderContext.GetLineColor();
242 Color aFillCol = rRenderContext.GetFillColor();
243 rRenderContext.SetLineColor();
244 Point aPointUL(x + 1, y + 1);
245 if (HasFocus())
246 {
247 rRenderContext.SetFillColor(aHighlightColor);
248 rRenderContext.DrawRect(getGridRectangle(aPointUL, aOutputSize));
249
250 rRenderContext.SetTextColor(aHighlightTextColor);
251 rRenderContext.DrawText(aPointTxTy, aCharStr);
252 }
253 else
254 {
255 rRenderContext.SetFillColor(aFaceColor);
256 rRenderContext.DrawRect(getGridRectangle(aPointUL, aOutputSize));
257
258 rRenderContext.SetLineColor(aLightColor);
259 rRenderContext.DrawLine(aPointUL, Point(x + nX - 1, y + 1));
260 rRenderContext.DrawLine(aPointUL, Point(x + 1, y + nY - 1));
261
262 rRenderContext.SetLineColor(aShadowColor);
263 rRenderContext.DrawLine(Point(x + 1, y + nY - 1), Point(x + nX - 1, y + nY - 1));
264 rRenderContext.DrawLine(Point(x + nX - 1, y + nY - 1), Point(x + nX - 1, y + 1));
265
266 rRenderContext.DrawText(aPointTxTy, aCharStr);
267 }
268 rRenderContext.SetLineColor(aLineCol);
269 rRenderContext.SetFillColor(aFillCol);
270 }
271 rRenderContext.SetTextColor(aTextCol);
272 }
273}
274
276{
277 if( nSelectedIndex >= 0 )
278 {
279 std::unordered_map<sal_Int32,sal_UCS4>::const_iterator got = m_aItemList.find (nSelectedIndex);
280
281 if(got == m_aItemList.end())
282 return 1;
283 else
284 return got->second;
285 }
286 return 1;
287}
288
290{
292 return;
293
294 Size aSize(GetOutputSizePixel());
295
296 vcl::Font aFont = rRenderContext.GetFont();
297 aFont.SetWeight(WEIGHT_LIGHT);
298 aFont.SetAlignment(ALIGN_TOP);
299 int nFontHeight = (aSize.Height() - 5) * 2 / (3 * ROW_COUNT);
300 maFontSize = rRenderContext.PixelToLogic(Size(0, nFontHeight));
301 aFont.SetFontSize(maFontSize);
302 aFont.SetTransparent(true);
303 rRenderContext.SetFont(aFont);
304 rRenderContext.GetFontCharMap(mxFontCharMap);
306
307 nX = aSize.Width() / COLUMN_COUNT;
308 nY = aSize.Height() / ROW_COUNT;
309
310 //scrollbar settings -- error
311 int nLastRow = (nCount - 1 + COLUMN_COUNT) / COLUMN_COUNT;
312 mxScrollArea->vadjustment_configure(mxScrollArea->vadjustment_get_value(), 0, nLastRow, 1, ROW_COUNT - 1, ROW_COUNT);
313
314 // rearrange CharSet element in sync with nX- and nY-multiples
315 Size aDrawSize(nX * COLUMN_COUNT, nY * ROW_COUNT);
316 m_nXGap = (aSize.Width() - aDrawSize.Width()) / 2;
317 m_nYGap = (aSize.Height() - aDrawSize.Height()) / 2;
318
319 mbRecalculateFont = false;
320}
321
322void SvxSearchCharSet::SelectIndex(int nNewIndex, bool bFocus)
323{
324 if (!mxFontCharMap.is())
326
327 if( nNewIndex < 0 )
328 {
329 mxScrollArea->vadjustment_set_value(0);
330 nSelectedIndex = bFocus ? 0 : -1;
331 Invalidate();
332 }
333 else if( nNewIndex < FirstInView() )
334 {
335 // need to scroll up to see selected item
336 int nOldPos = mxScrollArea->vadjustment_get_value();
337 int nDelta = (FirstInView() - nNewIndex + COLUMN_COUNT-1) / COLUMN_COUNT;
338 mxScrollArea->vadjustment_set_value(nOldPos - nDelta);
339 nSelectedIndex = nNewIndex;
340 Invalidate();
341 }
342 else if( nNewIndex > LastInView() )
343 {
344 // need to scroll down to see selected item
345 int nOldPos = mxScrollArea->vadjustment_get_value();
346 int nDelta = (nNewIndex - LastInView() + COLUMN_COUNT) / COLUMN_COUNT;
347 mxScrollArea->vadjustment_set_value(nOldPos + nDelta);
348
349 if( nNewIndex < nCount )
350 {
351 nSelectedIndex = nNewIndex;
352 Invalidate();
353 }
354 else if (nOldPos != mxScrollArea->vadjustment_get_value())
355 {
356 Invalidate();
357 }
358 }
359 else
360 {
361 nSelectedIndex = nNewIndex;
362 Invalidate();
363 }
364
365 if( nSelectedIndex >= 0 )
366 {
367#if 0
368 if( m_xAccessible.is() )
369 {
371 // Don't fire the focus event.
372 if ( bFocus )
373 m_xAccessible->fireEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), makeAny(pItem->GetAccessible()) ); // this call assures that m_pItem is set
374 else
375 m_xAccessible->fireEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS, Any(), makeAny(pItem->GetAccessible()) ); // this call assures that m_pItem is set
376
377 assert(pItem->m_xItem.is() && "No accessible created!");
378 Any aOldAny, aNewAny;
379 aNewAny <<= AccessibleStateType::FOCUSED;
380 // Don't fire the focus event.
381 if ( bFocus )
382 pItem->m_xItem->fireEvent( AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
383
384 aNewAny <<= AccessibleStateType::SELECTED;
385 pItem->m_xItem->fireEvent( AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
386 }
387#endif
388 }
389 aHighHdl.Call( this );
390}
391
393{
394}
395
397{
398 ItemsMap::iterator aFind = m_aItems.find(_nPos);
399 if ( aFind == m_aItems.end() )
400 {
401#if !ENABLE_WASM_STRIP_ACCESSIBILITY
402 OSL_ENSURE(m_xAccessible.is(), "Who wants to create a child of my table without a parent?");
403#endif
404 auto xItem = std::make_shared<svx::SvxShowCharSetItem>(*this,
405 m_xAccessible.get(), sal::static_int_cast< sal_uInt16 >(_nPos));
406 aFind = m_aItems.emplace(_nPos, xItem).first;
407 OUStringBuffer buf;
408 std::unordered_map<sal_Int32,sal_UCS4>::const_iterator got = m_aItemList.find (_nPos);
409 if (got != m_aItemList.end())
410 buf.appendUtf32(got->second);
411 aFind->second->maText = buf.makeStringAndClear();
412 Point pix = MapIndexToPixel( _nPos );
413 aFind->second->maRect = tools::Rectangle( Point( pix.X() + 1, pix.Y() + 1 ), Size(nX-1,nY-1) );
414 }
415
416 return aFind->second.get();
417}
418
420{
421 return nCount;
422}
423
425{
426 m_aItemList.clear();
427 nCount = 0;
428 Invalidate();
429}
430
432{
433 m_aItemList.insert(std::make_pair(nCount++, sChar));
434}
435
436/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define COLUMN_COUNT
Definition: charmap.hxx:46
#define ROW_COUNT
Definition: charmap.hxx:47
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
const vcl::KeyCode & GetKeyCode() const
const vcl::Font & GetFont() const
void SetFont(const vcl::Font &rNewFont)
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, o3tl::span< const sal_Int32 > pDXArray={}, o3tl::span< const sal_Bool > pKashidaArray={}, const SalLayoutGlyphs *pGlyphs=nullptr) const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
void DrawRect(const tools::Rectangle &rRect)
void DrawLine(const Point &rStartPt, const Point &rEndPt)
void SetLineColor()
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void SetTextColor(const Color &rColor)
bool GetFontCharMap(FontCharMapRef &rxFontCharMap) const
void SetFillColor()
const Color & GetLineColor() const
const Color & GetTextColor() const
tools::Long GetTextHeight() const
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
const Color & GetFillColor() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
const Color & GetFieldTextColor() const
const Color & GetShadowColor() const
const Color & GetLightColor() const
const Color & GetHighlightColor() const
const Color & GetFaceColor() const
const Color & GetHighlightTextColor() const
sal_UCS4 GetRangeMin() const
Definition: ucsubset.hxx:40
virtual void DrawChars_Impl(vcl::RenderContext &rRenderContext, int n1, int n2) override
void SelectCharacter(const Subset *sub)
std::unordered_map< sal_Int32, sal_UCS4 > m_aItemList
virtual bool KeyInput(const KeyEvent &rKEvt) override
virtual ~SvxSearchCharSet() override
virtual void SelectIndex(int index, bool bFocus=false) override
void AppendCharToList(sal_UCS4 cChar)
virtual void RecalculateFont(vcl::RenderContext &rRenderContext) override
virtual sal_Int32 getMaxCharCount() const override
SvxSearchCharSet(std::unique_ptr< weld::ScrolledWindow > pScrolledWindow, const VclPtr< VirtualDevice > &rDevice)
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
virtual int LastInView() const override
virtual sal_UCS4 GetSelectCharacter() const override
virtual svx::SvxShowCharSetItem * ImplGetItem(int _nPos) override
FontCharMapRef mxFontCharMap
Definition: charmap.hxx:139
int FirstInView() const
Definition: charmap.cxx:353
VclPtr< VirtualDevice > mxVirDev
Definition: charmap.hxx:58
sal_Int32 nSelectedIndex
Definition: charmap.hxx:137
void InitSettings(vcl::RenderContext &rRenderContext)
Definition: charmap.cxx:633
void getFavCharacterList()
Definition: charmap.cxx:197
Point MapIndexToPixel(int) const
Definition: charmap.cxx:368
Link< SvxShowCharSet *, void > aHighHdl
Definition: charmap.hxx:124
tools::Long nX
Definition: charmap.hxx:131
std::unique_ptr< weld::ScrolledWindow > mxScrollArea
Definition: charmap.hxx:60
Link< SvxShowCharSet *, void > aSelectHdl
Definition: charmap.hxx:122
tools::Long nY
Definition: charmap.hxx:132
tools::Long m_nYGap
Definition: charmap.hxx:134
Link< SvxShowCharSet *, void > aPreSelectHdl
Definition: charmap.hxx:125
bool mbRecalculateFont
Definition: charmap.hxx:143
tools::Long m_nXGap
Definition: charmap.hxx:133
ItemsMap m_aItems
Definition: charmap.hxx:120
tools::Rectangle getGridRectangle(const Point &rPointUL, const Size &rOutputSize) const
Definition: charmap.cxx:476
rtl::Reference< svx::SvxShowCharSetAcc > m_xAccessible
Definition: charmap.hxx:130
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr tools::Long Right() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
bool is() const
void SetFontSize(const Size &)
void SetTransparent(bool bTransparent)
void SetWeight(FontWeight)
void SetAlignment(TextAlign)
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
Size const & GetOutputSizePixel() const
int nCount
float y
float x
ALIGN_TOP
WEIGHT_LIGHT
OUString sName
sal_Int32 nIndex
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_ESCAPE
constexpr sal_uInt16 KEY_HOME
constexpr sal_uInt16 KEY_LEFT
constexpr sal_uInt16 KEY_PAGEDOWN
constexpr sal_uInt16 KEY_TAB
constexpr sal_uInt16 KEY_UP
constexpr sal_uInt16 KEY_RIGHT
constexpr sal_uInt16 KEY_DOWN
constexpr sal_uInt16 KEY_SPACE
constexpr sal_uInt16 KEY_PAGEUP
constexpr sal_uInt16 KEY_END
int n2
int n1
int i
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)
Simple struct to hold some information about the single items of the table.
Definition: charmapacc.hxx:46
css::uno::Reference< css::accessibility::XAccessible > GetAccessible()
Definition: charmapacc.cxx:58
rtl::Reference< SvxShowCharSetItemAcc > m_xItem
Definition: charmapacc.hxx:51
sal_uInt32 sal_UCS4
sal_Int32 _nPos