1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <osl/file.hxx>
11 #include <emojiview.hxx>
12 #include <emojiviewitem.hxx>
13 #include <rtl/bootstrap.hxx>
14 #include <sal/log.hxx>
15 #include <config_folders.h>
16 #include <officecfg/Office/Common.hxx>
17 #include <comphelper/processfactory.hxx>
18 #include <vcl/event.hxx>
19 #include <vcl/svapp.hxx>
21 #include <orcus/json_document_tree.hpp>
22 #include <orcus/config.hpp>
23 #include <orcus/pstring.hpp>
27 using namespace ::com::sun::star
;
29 bool ViewFilter_Category::isFilteredCategory(FILTER_CATEGORY filter
, const OUString
&rCategory
)
33 if (filter
== FILTER_CATEGORY::PEOPLE
)
34 bRet
= rCategory
.match("people");
35 else if (filter
== FILTER_CATEGORY::NATURE
)
36 bRet
= rCategory
.match("nature");
37 else if (filter
== FILTER_CATEGORY::FOOD
)
38 bRet
= rCategory
.match("food");
39 else if (filter
== FILTER_CATEGORY::ACTIVITY
)
40 bRet
= rCategory
.match("activity");
41 else if (filter
== FILTER_CATEGORY::TRAVEL
)
42 bRet
= rCategory
.match("travel");
43 else if (filter
== FILTER_CATEGORY::OBJECTS
)
44 bRet
= rCategory
.match("objects");
45 else if (filter
== FILTER_CATEGORY::SYMBOLS
)
46 bRet
= rCategory
.match("symbols");
47 else if (filter
== FILTER_CATEGORY::FLAGS
)
48 bRet
= rCategory
.match("flags");
49 else if (filter
== FILTER_CATEGORY::UNICODE9
)
50 bRet
= rCategory
.match("unicode9");
55 bool ViewFilter_Category::operator () (const ThumbnailViewItem
*pItem
)
57 const EmojiViewItem
*pViewItem
= dynamic_cast<const EmojiViewItem
*>(pItem
);
59 return isFilteredCategory(mCategory
, pViewItem
->getCategory());
64 EmojiView::EmojiView(std::unique_ptr
<weld::ScrolledWindow
> xWindow
)
65 : ThumbnailView(std::move(xWindow
), nullptr)
67 // locate json data file
68 OUString
aURL("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER
"/emojiconfig/emoji.json");
69 rtl::Bootstrap::expandMacros(aURL
);
72 osl::FileBase::getSystemPathFromFileURL(aURL
, aPath
);
73 std::string strPath
= OUStringToOString(aPath
, RTL_TEXTENCODING_UTF8
).getStr();
75 std::ifstream
file(strPath
);
79 msJSONData
= std::string((std::istreambuf_iterator
<char>(file
)), std::istreambuf_iterator
<char>());
80 if(msJSONData
.empty())
84 void EmojiView::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
86 ThumbnailView::SetDrawingArea(pDrawingArea
);
88 if (vcl::Window
* pDefaultDevice
= dynamic_cast<vcl::Window
*>(Application::GetDefaultDevice()))
90 uno::Reference
<uno::XComponentContext
> xContext(comphelper::getProcessComponentContext());
91 OUString
sFontName(officecfg::Office::Common::Misc::EmojiFont::get(xContext
));
92 vcl::Font aFont
= pDrawingArea
->get_font();
93 aFont
.SetFamilyName(sFontName
);
94 OutputDevice
& rDevice
= pDrawingArea
->get_ref_device();
95 pDefaultDevice
->SetPointFont(rDevice
, aFont
);
98 mpItemAttrs
->aFontSize
.setX(ITEM_MAX_WIDTH
- 2*ITEM_PADDING
);
99 mpItemAttrs
->aFontSize
.setY(ITEM_MAX_HEIGHT
- 2*ITEM_PADDING
);
102 EmojiView::~EmojiView()
106 void EmojiView::Populate()
108 if (msJSONData
.empty())
110 SAL_WARN("sfx", "Emoji config data is empty");
114 // Populate view using the orcus json parser
115 using node
= orcus::json::node
;
117 // default json config
118 orcus::json_config config
;
120 orcus::json::document_tree aEmojiInfo
;
122 // Load JSON string into a document tree.
123 aEmojiInfo
.load(msJSONData
, config
);
125 node root
= aEmojiInfo
.get_document_root();
126 std::vector
<orcus::pstring
> keys
= root
.keys();
128 for (auto const& key
: keys
)
130 node value
= root
.child(key
);
132 if(value
.type() == orcus::json::node_t::object
)
134 // iterate each element to get the keys
135 std::vector
<orcus::pstring
> aEmojiParams
= value
.keys();
136 OUString sTitle
, sCategory
, sName
;
137 bool bDuplicate
= false;
139 for (auto const& emojiParam
: aEmojiParams
)
141 node prop
= value
.child(emojiParam
);
143 // get values of parameters in AppendItem() function
144 if(emojiParam
== "unicode")
146 sTitle
= OStringToOUString(OString( prop
.string_value().get(), prop
.string_value().size() ), RTL_TEXTENCODING_UTF8
);
148 else if(emojiParam
== "category")
150 sCategory
= OStringToOUString(OString( prop
.string_value().get(), prop
.string_value().size() ), RTL_TEXTENCODING_UTF8
);
152 else if(emojiParam
== "name")
154 sName
= OStringToOUString(OString( prop
.string_value().get(), prop
.string_value().size() ), RTL_TEXTENCODING_UTF8
);
156 else if(emojiParam
== "duplicate")
162 // Don't append if a duplicate emoji
165 AppendItem(sTitle
, sCategory
, sName
);
171 bool EmojiView::MouseButtonDown( const MouseEvent
& rMEvt
)
177 size_t nPos
= ImplGetItem(rMEvt
.GetPosPixel());
178 ThumbnailViewItem
* pItem
= ImplGetItem(nPos
);
181 maInsertEmojiHdl
.Call(pItem
);
187 bool EmojiView::KeyInput( const KeyEvent
& rKEvt
)
189 vcl::KeyCode aKeyCode
= rKEvt
.GetKeyCode();
191 if(aKeyCode
== ( KEY_MOD1
| KEY_A
) )
193 for (ThumbnailViewItem
* pItem
: mFilteredItemList
)
195 if (!pItem
->isSelected())
197 pItem
->setSelection(true);
201 if (IsReallyVisible() && IsUpdateMode())
206 return ThumbnailView::KeyInput(rKEvt
);
209 void EmojiView::setInsertEmojiHdl(const Link
<ThumbnailViewItem
*, void> &rLink
)
211 maInsertEmojiHdl
= rLink
;
214 void EmojiView::AppendItem(const OUString
&rTitle
, const OUString
&rCategory
, const OUString
&rName
)
216 std::unique_ptr
<EmojiViewItem
> pItem(new EmojiViewItem(*this, getNextItemId()));
218 pItem
->maTitle
= rTitle
;
219 pItem
->setCategory(rCategory
);
220 pItem
->setHelpText(rName
);
222 ThumbnailView::AppendItem(std::move(pItem
));
224 CalculateItemPositions();
227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */