xref: /core/framework/source/uiconfiguration/CommandImageResolver.cxx (revision dcfc32914fe1d5239f9cbcb46a286f1a2e2d437e)
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 
10 #include "CommandImageResolver.hxx"
11 #include <vcl/settings.hxx>
12 #include <vcl/svapp.hxx>
13 #include <rtl/ustrbuf.hxx>
14 #include <tools/urlobj.hxx>
15 
16 using css::uno::Sequence;
17 
18 namespace vcl
19 {
20 
21 namespace
22 {
23 
24 std::map<std::tuple<ImageType, ImageWritingDirection>, OUString> const ImageType_Prefixes{
25     { { ImageType::Size16, ImageWritingDirection::DontCare }, u"cmd/sc_"_ustr },
26     { { ImageType::Size26, ImageWritingDirection::DontCare }, u"cmd/lc_"_ustr },
27     { { ImageType::Size32, ImageWritingDirection::DontCare }, u"cmd/32/"_ustr },
28     { { ImageType::Size16, ImageWritingDirection::RightLeftTopBottom }, u"cmd/rltb/sc_"_ustr },
29     { { ImageType::Size26, ImageWritingDirection::RightLeftTopBottom }, u"cmd/rltb/lc_"_ustr },
30     { { ImageType::Size32, ImageWritingDirection::RightLeftTopBottom }, u"cmd/rltb/32/"_ustr },
31 };
32 
lclConvertToCanonicalName(const OUString & rFileName)33 OUString lclConvertToCanonicalName(const OUString& rFileName)
34 {
35     bool bRemoveSlash(true);
36     sal_Int32 nLength = rFileName.getLength();
37     const sal_Unicode* pString = rFileName.getStr();
38 
39     OUStringBuffer aBuffer(nLength*2);
40 
41     for (sal_Int32 i = 0; i < nLength; i++)
42     {
43         const sal_Unicode cCurrentChar = pString[i];
44         switch (cCurrentChar)
45         {
46             // map forbidden characters to escape
47             case '/':
48                 if (!bRemoveSlash)
49                     aBuffer.append("%2f");
50                 break;
51             case '\\': aBuffer.append("%5c"); bRemoveSlash = false; break;
52             case ':':  aBuffer.append("%3a"); bRemoveSlash = false; break;
53             case '*':  aBuffer.append("%2a"); bRemoveSlash = false; break;
54             case '?':  aBuffer.append("%3f"); bRemoveSlash = false; break;
55             case '<':  aBuffer.append("%3c"); bRemoveSlash = false; break;
56             case '>':  aBuffer.append("%3e"); bRemoveSlash = false; break;
57             case '|':  aBuffer.append("%7c"); bRemoveSlash = false; break;
58             default:
59                 aBuffer.append(cCurrentChar); bRemoveSlash = false; break;
60         }
61     }
62     return aBuffer.makeStringAndClear();
63 }
64 
65 } // end anonymous namespace
66 
CommandImageResolver()67 CommandImageResolver::CommandImageResolver()
68 {
69 }
70 
~CommandImageResolver()71 CommandImageResolver::~CommandImageResolver()
72 {
73 }
74 
registerCommands(const Sequence<OUString> & aCommandSequence)75 void CommandImageResolver::registerCommands(const Sequence<OUString>& aCommandSequence)
76 {
77     sal_Int32 nSequenceSize = aCommandSequence.getLength();
78 
79     m_aImageCommandNameVector.resize(nSequenceSize);
80     m_aImageNameVector.resize(nSequenceSize);
81 
82     for (sal_Int32 i = 0; i < nSequenceSize; ++i)
83     {
84         const OUString& aCommandName(aCommandSequence[i]);
85         OUString aImageName;
86 
87         m_aImageCommandNameVector[i] = aCommandName;
88 
89         if (aCommandName.indexOf(".uno:") != 0)
90         {
91             INetURLObject aUrlObject(aCommandName, INetURLObject::EncodeMechanism::All);
92             aImageName = aUrlObject.GetURLPath();
93             aImageName = lclConvertToCanonicalName(aImageName);
94         }
95         else
96         {
97             // just remove the schema
98             if (aCommandName.getLength() > 5)
99                 aImageName = aCommandName.copy(5);
100 
101             // Search for query part.
102             if (aImageName.indexOf('?') != -1)
103                 aImageName = lclConvertToCanonicalName(aImageName);
104         }
105 
106         // Image names are not case-dependent. Always use lower case characters to
107         // reflect this.
108         aImageName = aImageName.toAsciiLowerCase() + ".png";
109 
110         m_aImageNameVector[i] = aImageName;
111         m_aCommandToImageNameMap[aCommandName] = aImageName;
112     }
113 }
114 
hasImage(const OUString & rCommandURL)115 bool CommandImageResolver::hasImage(const OUString& rCommandURL)
116 {
117     CommandToImageNameMap::const_iterator pIterator = m_aCommandToImageNameMap.find(rCommandURL);
118     return pIterator != m_aCommandToImageNameMap.end();
119 }
120 
getImageList(ImageType nImageType,ImageWritingDirection nImageDir)121 ImageList* CommandImageResolver::getImageList(ImageType nImageType, ImageWritingDirection nImageDir)
122 {
123     const OUString sIconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
124 
125     if (sIconTheme != m_sIconTheme)
126     {
127         m_sIconTheme = sIconTheme;
128         m_pImageList.clear();
129     }
130 
131     auto stKey = std::make_tuple(nImageType, nImageDir);
132     if (auto it = m_pImageList.find(stKey); it != m_pImageList.end())
133     {
134         return it->second.get();
135     }
136 
137     const OUString& sIconPath = ImageType_Prefixes.at(stKey);
138     auto pImageList = std::make_unique<ImageList>(m_aImageNameVector, sIconPath);
139 
140     return m_pImageList.emplace(stKey, std::move(pImageList)).first->second.get();
141 }
142 
getImageFromCommandURL(ImageType nImageType,ImageWritingDirection nImageDir,const OUString & rCommandURL)143 Image CommandImageResolver::getImageFromCommandURL(ImageType nImageType,
144                                                    ImageWritingDirection nImageDir,
145                                                    const OUString& rCommandURL)
146 {
147     CommandToImageNameMap::const_iterator pIterator = m_aCommandToImageNameMap.find(rCommandURL);
148     if (pIterator != m_aCommandToImageNameMap.end())
149     {
150         ImageList* pImageList = getImageList(nImageType, nImageDir);
151         return pImageList->GetImage(pIterator->second);
152     }
153     return Image();
154 }
155 
156 } // end namespace vcl
157 
158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
159