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{
44}
45
47{
48 int nIndex = FirstInView();
50 return std::min<int>(nIndex, getMaxCharCount() -1);
51}
52
54{
55 vcl::KeyCode aCode = rKEvt.GetKeyCode();
56
57 if (aCode.GetModifier())
58 return false;
59
60 int tmpSelected = nSelectedIndex;
61
62 bool bRet = true;
63
64 switch (aCode.GetCode())
65 {
66 case KEY_SPACE:
67 aSelectHdl.Call( this );
68 break;
69 case KEY_LEFT:
70 --tmpSelected;
71 break;
72 case KEY_RIGHT:
73 ++tmpSelected;
74 break;
75 case KEY_UP:
76 tmpSelected -= COLUMN_COUNT;
77 break;
78 case KEY_DOWN:
79 tmpSelected += COLUMN_COUNT;
80 break;
81 case KEY_PAGEUP:
82 tmpSelected -= ROW_COUNT * COLUMN_COUNT;
83 break;
84 case KEY_PAGEDOWN:
85 tmpSelected += ROW_COUNT * COLUMN_COUNT;
86 break;
87 case KEY_HOME:
88 tmpSelected = 0;
89 break;
90 case KEY_END:
91 tmpSelected = getMaxCharCount() - 1;
92 break;
93 case KEY_TAB: // some fonts have a character at these unicode control codes
94 case KEY_ESCAPE:
95 case KEY_RETURN:
96 bRet = false;
97 tmpSelected = - 1; // mark as invalid
98 break;
99 default:
100 tmpSelected = -1;
101 bRet = false;
102 break;
103 }
104
105 if ( tmpSelected >= 0 )
106 {
107 SelectIndex( tmpSelected, true );
108 aPreSelectHdl.Call( this );
109 }
110
111 return bRet;
112}
113
115{
116 if (!mxFontCharMap.is())
118
119 // get next available char of current font
120 sal_UCS4 cChar = sub->GetRangeMin();
121 int nMapIndex = 0;
122
123 while(cChar <= sub->GetRangeMax() && nMapIndex == 0)
124 {
125 auto it = std::find_if(m_aItemList.begin(), m_aItemList.end(),
126 [&cChar](const std::pair<const sal_Int32, sal_UCS4>& rItem) { return rItem.second == cChar; });
127 if (it != m_aItemList.end())
128 nMapIndex = it->first;
129 cChar++;
130 }
131
132 if(nMapIndex == 0)
133 SelectIndex( 0 );
134 else
135 SelectIndex( nMapIndex );
136 aHighHdl.Call(this);
137 // move selected item to top row if not in focus
138 //TO.DO aVscrollSB->SetThumbPos( nMapIndex / COLUMN_COUNT );
139 Invalidate();
140}
141
143{
144 InitSettings(rRenderContext);
145 RecalculateFont(rRenderContext);
146 DrawChars_Impl(rRenderContext, FirstInView(), LastInView());
147}
148
149void SvxSearchCharSet::DrawChars_Impl(vcl::RenderContext& rRenderContext, int n1, int n2)
150{
151 if (n1 > LastInView() || n2 < FirstInView())
152 return;
153
154 Size aOutputSize(GetOutputSizePixel());
155
156 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
157 const Color aWindowTextColor(rStyleSettings.GetFieldTextColor());
158 Color aHighlightColor(rStyleSettings.GetHighlightColor());
159 Color aHighlightTextColor(rStyleSettings.GetHighlightTextColor());
160 Color aFaceColor(rStyleSettings.GetFaceColor());
161 Color aLightColor(rStyleSettings.GetLightColor());
162 Color aShadowColor(rStyleSettings.GetShadowColor());
163
164 int i;
165 rRenderContext.SetLineColor(aShadowColor);
166 for (i = 1; i < COLUMN_COUNT; ++i)
167 {
168 rRenderContext.DrawLine(Point(nX * i + m_nXGap, 0),
169 Point(nX * i + m_nXGap, aOutputSize.Height()));
170 }
171 for (i = 1; i < ROW_COUNT; ++i)
172 {
173 rRenderContext.DrawLine(Point(0, nY * i + m_nYGap),
174 Point(aOutputSize.Width(), nY * i + m_nYGap));
175 }
176
177 int nTextHeight = rRenderContext.GetTextHeight();
178 tools::Rectangle aBoundRect;
179 for (i = n1; i <= n2; ++i)
180 {
181 Point pix = MapIndexToPixel(i);
182 int x = pix.X();
183 int y = pix.Y();
184
185 OUStringBuffer buf;
186 std::unordered_map<sal_Int32, sal_UCS4>::const_iterator got = m_aItemList.find (i);
188
189 if(got == m_aItemList.end())
190 continue;
191 else
192 sName = got->second;
193
194 buf.appendUtf32(sName);
195 OUString aCharStr(buf.makeStringAndClear());
196 int nTextWidth = rRenderContext.GetTextWidth(aCharStr);
197 int tx = x + (nX - nTextWidth + 1) / 2;
198 int ty = y + (nY - nTextHeight + 1) / 2;
199 Point aPointTxTy(tx, ty);
200
201 // adjust position before it gets out of bounds
202 if (rRenderContext.GetTextBoundRect(aBoundRect, aCharStr) && !aBoundRect.IsEmpty())
203 {
204 // zero advance width => use ink width to center glyph
205 if (!nTextWidth)
206 {
207 aPointTxTy.setX( x - aBoundRect.Left() + (nX - aBoundRect.GetWidth() + 1) / 2 );
208 }
209
210 aBoundRect += aPointTxTy;
211
212 // shift back vertically if needed
213 int nYLDelta = aBoundRect.Top() - y;
214 int nYHDelta = (y + nY) - aBoundRect.Bottom();
215 if (nYLDelta <= 0)
216 aPointTxTy.AdjustY( -(nYLDelta - 1) );
217 else if (nYHDelta <= 0)
218 aPointTxTy.AdjustY(nYHDelta - 1 );
219
220 // shift back horizontally if needed
221 int nXLDelta = aBoundRect.Left() - x;
222 int nXHDelta = (x + nX) - aBoundRect.Right();
223 if (nXLDelta <= 0)
224 aPointTxTy.AdjustX( -(nXLDelta - 1) );
225 else if (nXHDelta <= 0)
226 aPointTxTy.AdjustX(nXHDelta - 1 );
227 }
228
229 // tdf#109214 - highlight the favorite characters
230 if (isFavChar(aCharStr, mxVirDev->GetFont().GetFamilyName()))
231 {
232 const Color aLineCol = rRenderContext.GetLineColor();
233 rRenderContext.SetLineColor(aHighlightColor);
234 rRenderContext.SetFillColor(COL_TRANSPARENT);
235 // Outer border
236 rRenderContext.DrawRect(tools::Rectangle(Point(x - 1, y - 1), Size(nX + 3, nY + 3)), 1, 1);
237 // Inner border
238 rRenderContext.DrawRect(tools::Rectangle(Point(x, y), Size(nX + 1, nY + 1)), 1, 1);
239 rRenderContext.SetLineColor(aLineCol);
240 }
241
242 Color aTextCol = rRenderContext.GetTextColor();
243 if (i != nSelectedIndex)
244 {
245 rRenderContext.SetTextColor(aWindowTextColor);
246 rRenderContext.DrawText(aPointTxTy, aCharStr);
247 }
248 else
249 {
250 Color aLineCol = rRenderContext.GetLineColor();
251 Color aFillCol = rRenderContext.GetFillColor();
252 rRenderContext.SetLineColor();
253 Point aPointUL(x + 1, y + 1);
254 if (HasFocus())
255 {
256 rRenderContext.SetFillColor(aHighlightColor);
257 rRenderContext.DrawRect(getGridRectangle(aPointUL, aOutputSize));
258
259 rRenderContext.SetTextColor(aHighlightTextColor);
260 rRenderContext.DrawText(aPointTxTy, aCharStr);
261 }
262 else
263 {
264 rRenderContext.SetFillColor(aFaceColor);
265 rRenderContext.DrawRect(getGridRectangle(aPointUL, aOutputSize));
266
267 rRenderContext.SetLineColor(aLightColor);
268 rRenderContext.DrawLine(aPointUL, Point(x + nX - 1, y + 1));
269 rRenderContext.DrawLine(aPointUL, Point(x + 1, y + nY - 1));
270
271 rRenderContext.SetLineColor(aShadowColor);
272 rRenderContext.DrawLine(Point(x + 1, y + nY - 1), Point(x + nX - 1, y + nY - 1));
273 rRenderContext.DrawLine(Point(x + nX - 1, y + nY - 1), Point(x + nX - 1, y + 1));
274
275 rRenderContext.DrawText(aPointTxTy, aCharStr);
276 }
277 rRenderContext.SetLineColor(aLineCol);
278 rRenderContext.SetFillColor(aFillCol);
279 }
280 rRenderContext.SetTextColor(aTextCol);
281 }
282
283 // tdf#141319 - mark empty/unused cells
284 if (n2 - n1 < ROW_COUNT * COLUMN_COUNT)
285 {
286 rRenderContext.SetFillColor(rStyleSettings.GetDisableColor());
287 for (i = n2 - n1 + 1; i < ROW_COUNT * COLUMN_COUNT; i++)
288 {
289 Point pix = MapIndexToPixel(i + n1);
290 rRenderContext.DrawRect(
291 tools::Rectangle(Point(pix.X(), pix.Y()), Size(nX + 2, nY + 2)));
292 }
293 }
294}
295
297{
298 if( nSelectedIndex >= 0 )
299 {
300 std::unordered_map<sal_Int32,sal_UCS4>::const_iterator got = m_aItemList.find (nSelectedIndex);
301
302 if(got == m_aItemList.end())
303 return 1;
304 else
305 return got->second;
306 }
307 return 1;
308}
309
311{
313 return;
314
315 Size aSize(GetOutputSizePixel());
316
317 vcl::Font aFont = rRenderContext.GetFont();
318 aFont.SetWeight(WEIGHT_LIGHT);
319 aFont.SetAlignment(ALIGN_TOP);
320 int nFontHeight = (aSize.Height() - 5) * 2 / (3 * ROW_COUNT);
321 maFontSize = rRenderContext.PixelToLogic(Size(0, nFontHeight));
322 aFont.SetFontSize(maFontSize);
323 aFont.SetTransparent(true);
324 rRenderContext.SetFont(aFont);
325 rRenderContext.GetFontCharMap(mxFontCharMap);
326 m_aItems.clear();
328
329 nX = aSize.Width() / COLUMN_COUNT;
330 nY = aSize.Height() / ROW_COUNT;
331
333
334 // rearrange CharSet element in sync with nX- and nY-multiples
335 Size aDrawSize(nX * COLUMN_COUNT, nY * ROW_COUNT);
336 m_nXGap = (aSize.Width() - aDrawSize.Width()) / 2;
337 m_nYGap = (aSize.Height() - aDrawSize.Height()) / 2;
338
339 mbRecalculateFont = false;
340}
341
343{
344 //scrollbar settings
345 int nLastRow = (getMaxCharCount() - 1 + COLUMN_COUNT) / COLUMN_COUNT;
346 mxScrollArea->vadjustment_configure(mxScrollArea->vadjustment_get_value(), 0, nLastRow, 1, ROW_COUNT - 1, ROW_COUNT);
347}
348
349void SvxSearchCharSet::SelectIndex(int nNewIndex, bool bFocus)
350{
351 if (!mxFontCharMap.is())
353
354 if( nNewIndex < 0 )
355 {
356 mxScrollArea->vadjustment_set_value(0);
357 nSelectedIndex = bFocus ? 0 : -1;
358 Invalidate();
359 }
360 else if( nNewIndex < FirstInView() )
361 {
362 // need to scroll up to see selected item
363 int nOldPos = mxScrollArea->vadjustment_get_value();
364 int nDelta = (FirstInView() - nNewIndex + COLUMN_COUNT-1) / COLUMN_COUNT;
365 mxScrollArea->vadjustment_set_value(nOldPos - nDelta);
366 nSelectedIndex = nNewIndex;
367 Invalidate();
368 }
369 else if( nNewIndex > LastInView() )
370 {
371 // need to scroll down to see selected item
372 int nOldPos = mxScrollArea->vadjustment_get_value();
373 int nDelta = (nNewIndex - LastInView() + COLUMN_COUNT) / COLUMN_COUNT;
374 mxScrollArea->vadjustment_set_value(nOldPos + nDelta);
375
376 if (nNewIndex < getMaxCharCount())
377 {
378 nSelectedIndex = nNewIndex;
379 Invalidate();
380 }
381 else if (nOldPos != mxScrollArea->vadjustment_get_value())
382 {
383 Invalidate();
384 }
385 }
386 else
387 {
388 nSelectedIndex = nNewIndex;
389 Invalidate();
390 }
391
392 if( nSelectedIndex >= 0 )
393 {
394#if 0
395 if( m_xAccessible.is() )
396 {
398 // Don't fire the focus event.
399 if ( bFocus )
400 m_xAccessible->fireEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), makeAny(pItem->GetAccessible()) ); // this call assures that m_pItem is set
401 else
402 m_xAccessible->fireEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS, Any(), makeAny(pItem->GetAccessible()) ); // this call assures that m_pItem is set
403
404 assert(pItem->m_xItem.is() && "No accessible created!");
405 Any aOldAny, aNewAny;
406 aNewAny <<= AccessibleStateType::FOCUSED;
407 // Don't fire the focus event.
408 if ( bFocus )
409 pItem->m_xItem->fireEvent( AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
410
411 aNewAny <<= AccessibleStateType::SELECTED;
412 pItem->m_xItem->fireEvent( AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
413 }
414#endif
415 }
416 aHighHdl.Call( this );
417}
418
420{
421}
422
424{
425 ItemsMap::iterator aFind = m_aItems.find(_nPos);
426 if ( aFind == m_aItems.end() )
427 {
428#if !ENABLE_WASM_STRIP_ACCESSIBILITY
429 OSL_ENSURE(m_xAccessible.is(), "Who wants to create a child of my table without a parent?");
430#endif
431 auto xItem = std::make_shared<svx::SvxShowCharSetItem>(*this,
432 m_xAccessible.get(), sal::static_int_cast< sal_uInt16 >(_nPos));
433 aFind = m_aItems.emplace(_nPos, xItem).first;
434 OUStringBuffer buf;
435 std::unordered_map<sal_Int32,sal_UCS4>::const_iterator got = m_aItemList.find (_nPos);
436 if (got != m_aItemList.end())
437 buf.appendUtf32(got->second);
438 aFind->second->maText = buf.makeStringAndClear();
439 Point pix = MapIndexToPixel( _nPos );
440 aFind->second->maRect = tools::Rectangle( Point( pix.X() + 1, pix.Y() + 1 ), Size(nX-1,nY-1) );
441 }
442
443 return aFind->second.get();
444}
445
447{
448 return m_aItemList.size();
449}
450
452{
453 m_aItemList.clear();
454 Invalidate();
455}
456
458{
459 m_aItemList.insert(std::make_pair(m_aItemList.size(), sChar));
460}
461
462/* 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)
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
void DrawRect(const tools::Rectangle &rRect)
void DrawLine(const Point &rStartPt, const Point &rEndPt)
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, KernArraySpan aDXArray=KernArraySpan(), o3tl::span< const sal_Bool > pKashidaArray={}, const SalLayoutGlyphs *pGlyphs=nullptr) const
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
const Color & GetDisableColor() 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:645
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
bool isFavChar(const OUString &sTitle, const OUString &rFont)
Definition: charmap.cxx:210
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
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
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:44
css::uno::Reference< css::accessibility::XAccessible > GetAccessible()
Definition: charmapacc.cxx:59
rtl::Reference< SvxShowCharSetItemAcc > m_xItem
Definition: charmapacc.hxx:49
sal_uInt32 sal_UCS4
sal_Int32 _nPos