LibreOffice Module fpicker (master) 1
breadcrumb.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
10#include <tools/urlobj.hxx>
11#include <vcl/svapp.hxx>
12#include "breadcrumb.hxx"
13
15 : m_pParent(pParent)
16 , m_nMaxWidth(m_pParent->get_preferred_size().Width())
17{
18 m_pParent->connect_size_allocate(LINK(this, Breadcrumb, SizeAllocHdl));
20 appendField(); // root
21}
22
23IMPL_LINK(Breadcrumb, SizeAllocHdl, const Size&, rSize, void)
24{
25 m_nMaxWidth = rSize.Width();
26}
27
29{
31}
32
33void Breadcrumb::EnableFields( bool bEnable )
34{
35 if( bEnable )
36 {
38 int nSegments = aURL.getSegmentCount();
39 m_aSegments[nSegments]->m_xLink->set_sensitive(false);
40 }
41}
42
44{
45 m_aClickHdl = rLink;
46}
47
48const OUString& Breadcrumb::GetHdlURL() const
49{
50 return m_sClickedURL;
51}
52
53void Breadcrumb::SetRootName( const OUString& rURL )
54{
55 m_sRootName = rURL;
56
57 // we changed root - clear all fields
58 for (size_t i = 1; i < m_aSegments.size(); ++i)
59 {
60 m_aSegments[i]->m_xLink->set_label("");
61
62 m_aSegments[i]->m_xLink->hide();
63 m_aSegments[i]->m_xSeparator->hide();
64 m_aSegments[i]->m_xLink->set_sensitive(true);
65 }
66}
67
68void Breadcrumb::SetURL( const OUString& rURL )
69{
70 m_aCurrentURL = rURL;
71 INetURLObject aURL(rURL);
72 aURL.setFinalSlash();
73
75
76 int nSegments = aURL.getSegmentCount();
77
78 size_t nVecSizeRequired = nSegments + 1;
79
80 while (m_aSegments.size() < nVecSizeRequired)
82
83 // fill the fields under root
84 for (int i = nSegments; i; --i)
85 {
87 OUString sLink = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
88
90 {
91 if( m_aSegments[i]->m_xLink->get_label() != sLabel )
92 bClear = true;
93 }
94
95 m_aSegments[i]->m_xLink->hide();
96 m_aSegments[i]->m_xLink->set_label(sLabel);
97 m_aSegments[i]->m_xLink->set_sensitive(true);
98 m_aSegments[i]->m_xLink->set_uri(sLink);
99 m_aUris[m_aSegments[i]->m_xLink.get()] = sLink;
100
101 m_aSegments[i]->m_xSeparator->hide();
102
103 aURL.removeSegment();
104 }
105
106 OUString sRootPath = aURL.GetMainURL(INetURLObject::DecodeMechanism::WithCharset);
107
108 // root field
109 m_aSegments[0]->m_xLink->set_label( m_sRootName );
110 m_aSegments[0]->m_xLink->set_sensitive(true);
111 m_aSegments[0]->m_xLink->set_uri(sRootPath);
112 m_aUris[m_aSegments[0]->m_xLink.get()] = sRootPath;
113
114 // clear unused fields
115 for (size_t i = nSegments + 1; i < m_aSegments.size(); i++ )
116 {
117 if( bClear )
118 m_aSegments[i]->m_xLink->set_label( "" );
119
120 m_aSegments[i]->m_xLink->hide();
121 m_aSegments[i]->m_xSeparator->hide();
122 m_aSegments[i]->m_xLink->set_sensitive(true);
123 }
124
125 // show fields
126 unsigned int nSeparatorWidth = m_aSegments[0]->m_xSeparator->get_preferred_size().Width();
127 unsigned int nCurrentWidth = 0;
128 unsigned int nLastVisible = nSegments;
129
130 bool bRight = ( m_eMode == SvtBreadcrumbMode::ALL_VISITED );
131 bool bLeft = true;
132
133 int i = 0;
134
135 while( bLeft || bRight )
136 {
137 if( nSegments - i == -1 )
138 bLeft = false;
139
140 if( bLeft )
141 {
142 unsigned int nIndex = nSegments - i;
143
144 if( showField( nIndex, m_nMaxWidth - nCurrentWidth ) )
145 {
146 nCurrentWidth += m_aSegments[nIndex]->m_xLink->get_preferred_size().Width()
147 + nSeparatorWidth + 2*SPACING;
148 }
149 else
150 {
151 // label is too long
152 if( nSegments != 0 )
153 {
154 m_aSegments[0]->m_xLink->set_label("...");
155 m_aSegments[0]->m_xLink->set_sensitive(false);
156 }
157 bLeft = false;
158 }
159 }
160
161 if( nSegments + i == static_cast<int>(m_aSegments.size()) )
162 bRight = false;
163
164 if( i != 0 && bRight )
165 {
166 unsigned int nIndex = nSegments + i;
167
168 if( m_aSegments[nIndex]->m_xLink->get_label().isEmpty() )
169 {
170 bRight = false;
171 }
172 else if( showField( nIndex, m_nMaxWidth - nCurrentWidth ) )
173 {
174 nCurrentWidth += m_aSegments[nIndex]->m_xLink->get_preferred_size().Width()
175 + nSeparatorWidth + 3*SPACING;
176 nLastVisible = nIndex;
177 }
178 else
179 {
180 bRight = false;
181 }
182 }
183
184 i++;
185 }
186
187 // current dir should be inactive
188 m_aSegments[nSegments]->m_xLink->set_sensitive(false);
189
190 // hide last separator
191 m_aSegments[nLastVisible]->m_xSeparator->hide();
192}
193
195{
196 m_eMode = eMode;
197}
198
200{
201 m_aSegments.emplace_back(std::make_unique<BreadcrumbPath>(m_pParent));
202 size_t nIndex = m_aSegments.size() - 1;
203 m_aSegments[nIndex]->m_xLink->hide();
204 m_aSegments[nIndex]->m_xLink->connect_activate_link(LINK(this, Breadcrumb, ClickLinkHdl));
205 m_aSegments[nIndex]->m_xSeparator->set_label( ">" );
206 m_aSegments[nIndex]->m_xSeparator->hide();
207}
208
209bool Breadcrumb::showField( unsigned int nIndex, unsigned int nWidthMax )
210{
211 m_aSegments[nIndex]->m_xLink->show();
212 m_aSegments[nIndex]->m_xSeparator->show();
213
214 unsigned int nSeparatorWidth = m_aSegments[0]->m_xSeparator->get_preferred_size().Width();
215 unsigned int nWidth = m_aSegments[nIndex]->m_xLink->get_preferred_size().Width()
216 + nSeparatorWidth + 3*SPACING;
217
218 if( nWidth > nWidthMax )
219 {
220 if( nIndex != 0 )
221 {
222 m_aSegments[nIndex]->m_xLink->hide();
223 m_aSegments[nIndex]->m_xSeparator->hide();
224 }
225
226 return false;
227 }
228
229 return true;
230}
231
232IMPL_LINK(Breadcrumb, ClickLinkHdl, weld::LinkButton&, rLink, bool)
233{
234 m_sClickedURL = m_aUris[&rLink];
235 return m_aClickHdl.Call(this);
236}
237
239 : m_xBuilder(Application::CreateBuilder(pContainer, "fps/ui/breadcrumb.ui"))
240 , m_xContainer(m_xBuilder->weld_container("container"))
241 , m_xLink(m_xBuilder->weld_link_button("link"))
242 , m_xSeparator(m_xBuilder->weld_label("label"))
243{
244}
245
246/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::shared_ptr< MetadatableClipboard > m_xLink
IMPL_LINK(Breadcrumb, SizeAllocHdl, const Size &, rSize, void)
Definition: breadcrumb.cxx:23
#define SPACING
Definition: breadcrumb.hxx:16
SvtBreadcrumbMode
Definition: breadcrumb.hxx:19
@ ALL_VISITED
Definition: breadcrumb.hxx:21
@ ONLY_CURRENT_PATH
Definition: breadcrumb.hxx:20
Breadcrumb(weld::Container *pParent)
Definition: breadcrumb.cxx:14
bool showField(unsigned int nIndex, unsigned int nWidthMax)
Definition: breadcrumb.cxx:209
void EnableFields(bool bEnable)
Definition: breadcrumb.cxx:33
int m_nMaxWidth
Definition: breadcrumb.hxx:37
weld::Container * m_pParent
Definition: breadcrumb.hxx:36
SvtBreadcrumbMode m_eMode
Definition: breadcrumb.hxx:46
void connect_clicked(const Link< Breadcrumb *, bool > &rLink)
Definition: breadcrumb.cxx:43
void SetMode(SvtBreadcrumbMode eMode)
Definition: breadcrumb.cxx:194
void SetRootName(const OUString &rURL)
Definition: breadcrumb.cxx:53
OUString m_aCurrentURL
Definition: breadcrumb.hxx:44
const OUString & GetHdlURL() const
Definition: breadcrumb.cxx:48
OUString m_sClickedURL
Definition: breadcrumb.hxx:43
std::map< weld::LinkButton *, OUString > m_aUris
Definition: breadcrumb.hxx:40
OUString m_sRootName
Definition: breadcrumb.hxx:42
std::vector< std::unique_ptr< BreadcrumbPath > > m_aSegments
Definition: breadcrumb.hxx:39
Link< Breadcrumb *, bool > m_aClickHdl
Definition: breadcrumb.hxx:48
void SetURL(const OUString &rURL)
Definition: breadcrumb.cxx:68
void appendField()
Definition: breadcrumb.cxx:199
virtual void connect_size_allocate(const Link< const Size &, void > &rLink)
URL aURL
sal_Int32 nIndex
Mode eMode
int i
Reference< XNameAccess > m_xContainer
BreadcrumbPath(weld::Container *pParent)
Definition: breadcrumb.cxx:238