Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / fpicker / source / office / breadcrumb.cxx
bloba300a32cc1d0f9c71bc296e72698db8d54df085f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <tools/urlobj.hxx>
11 #include <vcl/svapp.hxx>
12 #include "breadcrumb.hxx"
14 Breadcrumb::Breadcrumb(weld::Container* pParent)
15 : m_pParent(pParent)
16 , m_nMaxWidth(m_pParent->get_preferred_size().Width())
18 m_pParent->connect_size_allocate(LINK(this, Breadcrumb, SizeAllocHdl));
19 m_eMode = SvtBreadcrumbMode::ONLY_CURRENT_PATH;
20 appendField(); // root
23 IMPL_LINK(Breadcrumb, SizeAllocHdl, const Size&, rSize, void)
25 m_nMaxWidth = rSize.Width();
28 Breadcrumb::~Breadcrumb()
30 m_pParent->connect_size_allocate(Link<const Size&, void>());
33 void Breadcrumb::EnableFields( bool bEnable )
35 if( bEnable )
37 INetURLObject aURL( m_aCurrentURL );
38 int nSegments = aURL.getSegmentCount();
39 m_aSegments[nSegments]->m_xLink->set_sensitive(false);
43 void Breadcrumb::connect_clicked( const Link<Breadcrumb*,bool>& rLink )
45 m_aClickHdl = rLink;
48 const OUString& Breadcrumb::GetHdlURL() const
50 return m_sClickedURL;
53 void Breadcrumb::SetRootName( const OUString& rURL )
55 m_sRootName = rURL;
57 // we changed root - clear all fields
58 for (size_t i = 1; i < m_aSegments.size(); ++i)
60 m_aSegments[i]->m_xLink->set_label("");
62 m_aSegments[i]->m_xLink->hide();
63 m_aSegments[i]->m_xSeparator->hide();
64 m_aSegments[i]->m_xLink->set_sensitive(true);
68 void Breadcrumb::SetURL( const OUString& rURL )
70 m_aCurrentURL = rURL;
71 INetURLObject aURL( rURL );
72 aURL.setFinalSlash();
73 //prepare the Host port
74 OUString sHostPort;
76 if( aURL.HasPort() )
78 sHostPort += ":" + OUString::number( aURL.GetPort() );
81 OUString sUser = aURL.GetUser( INetURLObject::DecodeMechanism::NONE );
82 OUString sPath = aURL.GetURLPath(INetURLObject::DecodeMechanism::WithCharset);
83 OUString sRootPath = INetURLObject::GetScheme( aURL.GetProtocol() )
84 + sUser
85 + ( sUser.isEmpty() ? OUString() : "@" )
86 + aURL.GetHost()
87 + sHostPort;
89 int nSegments = aURL.getSegmentCount();
90 unsigned int nPos = 0;
92 bool bClear = ( m_eMode == SvtBreadcrumbMode::ONLY_CURRENT_PATH );
94 // root field
95 m_aSegments[0]->m_xLink->set_label( m_sRootName );
96 m_aSegments[0]->m_xLink->set_sensitive(true);
97 m_aSegments[0]->m_xLink->set_uri(sRootPath);
98 m_aUris[m_aSegments[0]->m_xLink.get()] = sRootPath;
100 // fill the other fields
102 for( unsigned int i = 1; i < static_cast<unsigned int>(nSegments) + 1; i++ )
104 if( i >= m_aSegments.size() )
105 appendField();
107 unsigned int nEnd = sPath.indexOf( '/', nPos + 1 );
108 OUString sLabel = sPath.copy( nPos + 1, nEnd - nPos - 1 );
110 if( m_eMode == SvtBreadcrumbMode::ALL_VISITED )
112 if( m_aSegments[i]->m_xLink->get_label() != sLabel )
113 bClear = true;
116 m_aSegments[i]->m_xLink->set_label( sLabel );
117 m_aUris[m_aSegments[i]->m_xLink.get()] = sRootPath + sPath.copy(0, nEnd);
118 m_aSegments[i]->m_xLink->hide();
119 m_aSegments[i]->m_xLink->set_sensitive(true);
121 m_aSegments[i]->m_xSeparator->hide();
123 nPos = nEnd;
126 // clear unused fields
127 for (size_t i = nSegments + 1; i < m_aSegments.size(); i++ )
129 if( bClear )
130 m_aSegments[i]->m_xLink->set_label( "" );
132 m_aSegments[i]->m_xLink->hide();
133 m_aSegments[i]->m_xSeparator->hide();
134 m_aSegments[i]->m_xLink->set_sensitive(true);
137 // show fields
138 unsigned int nSeparatorWidth = m_aSegments[0]->m_xSeparator->get_preferred_size().Width();
139 unsigned int nCurrentWidth = 0;
140 unsigned int nLastVisible = nSegments;
142 bool bRight = ( m_eMode == SvtBreadcrumbMode::ALL_VISITED );
143 bool bLeft = true;
145 int i = 0;
147 while( bLeft || bRight )
149 if( nSegments - i == -1 )
150 bLeft = false;
152 if( bLeft )
154 unsigned int nIndex = nSegments - i;
156 if( showField( nIndex, m_nMaxWidth - nCurrentWidth ) )
158 nCurrentWidth += m_aSegments[nIndex]->m_xLink->get_preferred_size().Width()
159 + nSeparatorWidth + 2*SPACING;
161 else
163 // label is too long
164 if( nSegments != 0 )
166 m_aSegments[0]->m_xLink->set_label("...");
167 m_aSegments[0]->m_xLink->set_sensitive(false);
169 bLeft = false;
173 if( nSegments + i == static_cast<int>(m_aSegments.size()) )
174 bRight = false;
176 if( i != 0 && bRight )
178 unsigned int nIndex = nSegments + i;
180 if( m_aSegments[nIndex]->m_xLink->get_label().isEmpty() )
182 bRight = false;
184 else if( showField( nIndex, m_nMaxWidth - nCurrentWidth ) )
186 nCurrentWidth += m_aSegments[nIndex]->m_xLink->get_preferred_size().Width()
187 + nSeparatorWidth + 3*SPACING;
188 nLastVisible = nIndex;
190 else
192 bRight = false;
196 i++;
199 // current dir should be inactive
200 m_aSegments[nSegments]->m_xLink->set_sensitive(false);
202 // hide last separator
203 m_aSegments[nLastVisible]->m_xSeparator->hide();
206 void Breadcrumb::SetMode( SvtBreadcrumbMode eMode )
208 m_eMode = eMode;
211 void Breadcrumb::appendField()
213 m_aSegments.emplace_back(std::make_unique<BreadcrumbPath>(m_pParent));
214 size_t nIndex = m_aSegments.size() - 1;
215 m_aSegments[nIndex]->m_xLink->hide();
216 m_aSegments[nIndex]->m_xLink->connect_activate_link(LINK(this, Breadcrumb, ClickLinkHdl));
217 m_aSegments[nIndex]->m_xSeparator->set_label( ">" );
218 m_aSegments[nIndex]->m_xSeparator->hide();
221 bool Breadcrumb::showField( unsigned int nIndex, unsigned int nWidthMax )
223 m_aSegments[nIndex]->m_xLink->show();
224 m_aSegments[nIndex]->m_xSeparator->show();
226 unsigned int nSeparatorWidth = m_aSegments[0]->m_xSeparator->get_preferred_size().Width();
227 unsigned int nWidth = m_aSegments[nIndex]->m_xLink->get_preferred_size().Width()
228 + nSeparatorWidth + 3*SPACING;
230 if( nWidth > nWidthMax )
232 if( nIndex != 0 )
234 m_aSegments[nIndex]->m_xLink->hide();
235 m_aSegments[nIndex]->m_xSeparator->hide();
238 return false;
241 return true;
244 IMPL_LINK(Breadcrumb, ClickLinkHdl, weld::LinkButton&, rLink, bool)
246 m_sClickedURL = m_aUris[&rLink];
247 return m_aClickHdl.Call(this);
250 BreadcrumbPath::BreadcrumbPath(weld::Container* pContainer)
251 : m_xBuilder(Application::CreateBuilder(pContainer, "fps/ui/breadcrumb.ui"))
252 , m_xContainer(m_xBuilder->weld_container("container"))
253 , m_xLink(m_xBuilder->weld_link_button("link"))
254 , m_xSeparator(m_xBuilder->weld_label("label"))
258 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */