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 <LayerTabBar.hxx>
21 #include <svx/svdlayer.hxx>
22 #include <svx/svdpagv.hxx>
23 #include <vcl/commandevent.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/weld.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/viewfrm.hxx>
28
29 #include <helpids.h>
30 #include <app.hrc>
31 #include <strings.hrc>
32
33 #include <DrawViewShell.hxx>
34 #include <View.hxx>
35 #include <drawdoc.hxx>
36 #include <sdresid.hxx>
37 #include <unokywds.hxx>
38 #include <DrawDocShell.hxx>
39 #include <drawview.hxx>
40 #include <undolayer.hxx>
41
42 namespace sd {
43
44 /**
45 * default constructor
46 */
LayerTabBar(DrawViewShell * pViewSh,vcl::Window * pParent)47 LayerTabBar::LayerTabBar(DrawViewShell* pViewSh, vcl::Window* pParent)
48 : TabBar( pParent, WinBits( WB_BORDER | WB_3DLOOK | WB_SCROLL ) ),
49 DropTargetHelper( this ),
50 pDrViewSh(pViewSh)
51 {
52 EnableEditMode();
53 SetSizePixel(Size(0, 0));
54 SetMaxPageWidth( 150 );
55 SetHelpId( HID_SD_TABBAR_LAYERS );
56 }
57
~LayerTabBar()58 LayerTabBar::~LayerTabBar()
59 {
60 disposeOnce();
61 }
62
dispose()63 void LayerTabBar::dispose()
64 {
65 DropTargetHelper::dispose();
66 TabBar::dispose();
67 }
68
convertToLocalizedName(const OUString & rName)69 OUString LayerTabBar::convertToLocalizedName(const OUString& rName)
70 {
71 if ( rName == sUNO_LayerName_background )
72 return SdResId( STR_LAYER_BCKGRND );
73
74 if ( rName == sUNO_LayerName_background_objects )
75 return SdResId( STR_LAYER_BCKGRNDOBJ );
76
77 if ( rName == sUNO_LayerName_layout )
78 return SdResId( STR_LAYER_LAYOUT );
79
80 if ( rName == sUNO_LayerName_controls )
81 return SdResId( STR_LAYER_CONTROLS );
82
83 if ( rName == sUNO_LayerName_measurelines )
84 return SdResId( STR_LAYER_MEASURELINES );
85
86 return rName;
87 }
88
89 // Use a method name, that is specific to LayerTabBar to make code better readable
GetLayerName(sal_uInt16 nPageId) const90 OUString LayerTabBar::GetLayerName(sal_uInt16 nPageId) const
91 {
92 return GetAuxiliaryText(nPageId);
93 }
94
SetLayerName(sal_uInt16 nPageId,const OUString & rText)95 void LayerTabBar::SetLayerName( sal_uInt16 nPageId, const OUString& rText )
96 {
97 SetAuxiliaryText(nPageId, rText);
98 }
99
100 // Here "Page" is a tab in the LayerTabBar.
InsertPage(sal_uInt16 nPageId,const OUString & rText,TabBarPageBits nBits,sal_uInt16 nPos)101 void LayerTabBar::InsertPage( sal_uInt16 nPageId, const OUString& rText,
102 TabBarPageBits nBits, sal_uInt16 nPos)
103 {
104 OUString sLocalizedName(convertToLocalizedName(rText));
105 TabBar::InsertPage(nPageId, sLocalizedName, nBits, nPos );
106 SetLayerName(nPageId, rText);
107 }
108
SetPageText(sal_uInt16 nPageId,const OUString & rText)109 void LayerTabBar::SetPageText( sal_uInt16 nPageId, const OUString& rText )
110 {
111 OUString sLocalizedName(convertToLocalizedName(rText));
112 SetLayerName(nPageId, rText);
113 TabBar::SetPageText(nPageId, sLocalizedName);
114 }
115
IsLocalizedNameOfStandardLayer(std::u16string_view rName)116 bool LayerTabBar::IsLocalizedNameOfStandardLayer(std::u16string_view rName)
117 {
118 return ( rName == SdResId(STR_LAYER_LAYOUT)
119 || rName == SdResId(STR_LAYER_CONTROLS)
120 || rName == SdResId(STR_LAYER_MEASURELINES)
121 || rName == SdResId(STR_LAYER_BCKGRND)
122 || rName == SdResId(STR_LAYER_BCKGRNDOBJ) );
123 }
124
IsRealNameOfStandardLayer(std::u16string_view rName)125 bool LayerTabBar::IsRealNameOfStandardLayer(std::u16string_view rName)
126 {
127 return ( rName == sUNO_LayerName_layout
128 || rName == sUNO_LayerName_controls
129 || rName == sUNO_LayerName_measurelines
130 || rName == sUNO_LayerName_background
131 || rName == sUNO_LayerName_background_objects );
132 }
133
Select()134 void LayerTabBar::Select()
135 {
136 SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
137 pDispatcher->Execute(SID_SWITCHLAYER, SfxCallMode::ASYNCHRON);
138 }
139
MouseButtonDown(const MouseEvent & rMEvt)140 void LayerTabBar::MouseButtonDown(const MouseEvent& rMEvt)
141 {
142 bool bSetPageID=false;
143
144 if (rMEvt.IsLeft())
145 {
146 Point aPosPixel = rMEvt.GetPosPixel();
147 sal_uInt16 aTabId = GetPageId( PixelToLogic(aPosPixel) );
148 if (aTabId == 0)
149 {
150 SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
151 pDispatcher->Execute(SID_INSERTLAYER, SfxCallMode::SYNCHRON);
152
153 bSetPageID=true;
154 }
155 else if (rMEvt.IsMod2())
156 {
157 // direct editing of tab text
158 // make sure the clicked tab is the current tab otherwise Edit() acts on the wrong tab
159 if ( aTabId != GetCurPageId())
160 {
161 MouseEvent aSyntheticEvent (rMEvt.GetPosPixel(), 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0);
162 TabBar::MouseButtonDown(aSyntheticEvent);
163 }
164 }
165 else if (rMEvt.IsMod1() || rMEvt.IsShift())
166 {
167 // keyboard Shortcuts to change layer attributes
168
169 OUString aName(GetLayerName(aTabId));
170 SdrPageView* pPV = pDrViewSh->GetView()->GetSdrPageView();
171
172 // Save old state
173
174 bool bOldPrintable = pPV->IsLayerPrintable(aName);
175 bool bOldVisible = pPV->IsLayerVisible(aName);
176 bool bOldLocked = pPV->IsLayerLocked(aName);
177
178 bool bNewPrintable = bOldPrintable;
179 bool bNewVisible = bOldVisible;
180 bool bNewLocked = bOldLocked;
181
182 if (rMEvt.IsMod1() && rMEvt.IsShift())
183 {
184 // Shift+Ctrl: Toggle between layer printable / not printable
185 bNewPrintable = !bOldPrintable;
186 pPV->SetLayerPrintable(aName, bNewPrintable);
187 }
188 else if (rMEvt.IsShift())
189 {
190 // Shift: Toggle between layer visible / hidden
191 bNewVisible = !bOldVisible;
192 pPV->SetLayerVisible(aName, bNewVisible);
193 }
194 else // if (rMEvt.IsMod1())
195 {
196 // Ctrl: Toggle between layer locked / unlocked
197 bNewLocked = !bOldLocked;
198 pPV->SetLayerLocked(aName, bNewLocked);
199 }
200
201 pDrViewSh->ResetActualLayer();
202
203 // Add Undo action
204
205 ::sd::View* pView = pDrViewSh->GetView();
206 DrawView* pDrView = dynamic_cast<DrawView*>(pView);
207
208 SdDrawDocument& rDoc = pView->GetDoc();
209 SdrLayer* pLayer = rDoc.GetLayerAdmin().GetLayer(aName);
210
211 if (pLayer)
212 {
213 assert (pDrView && "Change layer attribute undo action is only working with a SdDrawView");
214 if(pDrView)
215 {
216 SfxUndoManager* pManager = rDoc.GetDocSh()->GetUndoManager();
217 std::unique_ptr<SdLayerModifyUndoAction> pAction(new SdLayerModifyUndoAction(
218 &rDoc,
219 pLayer,
220 aName,
221 pLayer->GetTitle(),
222 pLayer->GetDescription(),
223 bOldVisible,
224 bOldLocked,
225 bOldPrintable,
226 aName,
227 pLayer->GetTitle(),
228 pLayer->GetDescription(),
229 bNewVisible,
230 bNewLocked,
231 bNewPrintable
232 ));
233 pManager->AddUndoAction(std::move(pAction));
234 }
235 }
236
237 // Mark document changed
238
239 pView->GetDoc().SetChanged();
240 }
241 }
242
243 // If you insert a new layer you must not call TabBar::MouseButtonDown(rMEvt);
244 // because you want to activate the new layer
245 if( !bSetPageID )
246 TabBar::MouseButtonDown(rMEvt);
247 }
248
DoubleClick()249 void LayerTabBar::DoubleClick()
250 {
251 if (GetCurPageId() != 0)
252 {
253 SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
254 pDispatcher->Execute( SID_MODIFYLAYER, SfxCallMode::SYNCHRON );
255 }
256 }
257
258 /**
259 * AcceptDrop-Event
260 */
261
AcceptDrop(const AcceptDropEvent & rEvt)262 sal_Int8 LayerTabBar::AcceptDrop( const AcceptDropEvent& rEvt )
263 {
264 sal_Int8 nRet = DND_ACTION_NONE;
265
266 if( rEvt.mbLeaving )
267 EndSwitchPage();
268
269 if( !pDrViewSh->GetDocSh()->IsReadOnly() )
270 {
271 Point aPos( PixelToLogic( rEvt.maPosPixel ) );
272 OUString sLayerName( GetLayerName(GetPageId(aPos)) );
273 SdrLayerID nLayerId = pDrViewSh->GetView()->GetDoc().GetLayerAdmin().GetLayerID(sLayerName);
274
275 nRet = pDrViewSh->AcceptDrop( rEvt, *this, nullptr, SDRPAGE_NOTFOUND, nLayerId );
276
277 SwitchPage( aPos );
278 }
279
280 return nRet;
281 }
282
283 /**
284 * ExecuteDrop-Event
285 */
ExecuteDrop(const ExecuteDropEvent & rEvt)286 sal_Int8 LayerTabBar::ExecuteDrop( const ExecuteDropEvent& rEvt )
287 {
288 Point aPos( PixelToLogic(rEvt.maPosPixel) );
289 OUString sLayerName( GetLayerName(GetPageId(aPos)) );
290 SdrLayerID nLayerId = pDrViewSh->GetView()->GetDoc().GetLayerAdmin().GetLayerID(sLayerName);
291
292 sal_Int8 nRet = pDrViewSh->ExecuteDrop( rEvt, *this, nullptr, SDRPAGE_NOTFOUND, nLayerId );
293
294 EndSwitchPage();
295
296 return nRet;
297
298 }
299
Command(const CommandEvent & rCEvt)300 void LayerTabBar::Command(const CommandEvent& rCEvt)
301 {
302 if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
303 {
304 SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
305 pDispatcher->ExecutePopup("layertab");
306 }
307 }
308
StartRenaming()309 bool LayerTabBar::StartRenaming()
310 {
311 bool bOK = true;
312 OUString aLayerName = GetLayerName( GetEditPageId() );
313
314 if ( IsRealNameOfStandardLayer(aLayerName))
315 {
316 // It is not allowed to change these names
317 bOK = false;
318 }
319 else
320 {
321 ::sd::View* pView = pDrViewSh->GetView();
322
323 if ( pView->IsTextEdit() )
324 {
325 pView->SdrEndTextEdit();
326 }
327 }
328
329 return bOK;
330 }
331
AllowRenaming()332 TabBarAllowRenamingReturnCode LayerTabBar::AllowRenaming()
333 {
334 bool bOK = true;
335
336 // Check if names already exists
337 ::sd::View* pView = pDrViewSh->GetView();
338 SdDrawDocument& rDoc = pView->GetDoc();
339 OUString aLayerName = pView->GetActiveLayer();
340 SdrLayerAdmin& rLayerAdmin = rDoc.GetLayerAdmin();
341 OUString aNewName( GetEditText() );
342
343 if (aNewName.isEmpty() ||
344 (rLayerAdmin.GetLayer( aNewName ) && aLayerName != aNewName) )
345 {
346 // Name already exists.
347 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pDrViewSh->GetViewFrame()->GetFrameWeld(),
348 VclMessageType::Warning, VclButtonsType::Ok,
349 SdResId(STR_WARN_NAME_DUPLICATE)));
350 xWarn->run();
351 bOK = false;
352 }
353
354 if (bOK)
355 {
356 if ( IsLocalizedNameOfStandardLayer(aNewName) || IsRealNameOfStandardLayer(aNewName) )
357 {
358 // Standard layer names may not be changed.
359 bOK = false;
360 }
361 }
362
363 return bOK ? TABBAR_RENAMING_YES : TABBAR_RENAMING_NO;
364 }
365
EndRenaming()366 void LayerTabBar::EndRenaming()
367 {
368 if( IsEditModeCanceled() )
369 return;
370
371 ::sd::View* pView = pDrViewSh->GetView();
372 DrawView* pDrView = dynamic_cast<DrawView*>( pView );
373
374 SdDrawDocument& rDoc = pView->GetDoc();
375 OUString aLayerName = pView->GetActiveLayer();
376 SdrLayerAdmin& rLayerAdmin = rDoc.GetLayerAdmin();
377 SdrLayer* pLayer = rLayerAdmin.GetLayer(aLayerName);
378
379 if (!pLayer)
380 return;
381
382 OUString aNewName( GetEditText() );
383 assert (pDrView && "Rename layer undo action is only working with a SdDrawView");
384 if( pDrView )
385 {
386 SfxUndoManager* pManager = rDoc.GetDocSh()->GetUndoManager();
387 std::unique_ptr<SdLayerModifyUndoAction> pAction(new SdLayerModifyUndoAction(
388 &rDoc,
389 pLayer,
390 aLayerName,
391 pLayer->GetTitle(),
392 pLayer->GetDescription(),
393 pDrView->IsLayerVisible(aLayerName),
394 pDrView->IsLayerLocked(aLayerName),
395 pDrView->IsLayerPrintable(aLayerName),
396 aNewName,
397 pLayer->GetTitle(),
398 pLayer->GetDescription(),
399 pDrView->IsLayerVisible(aLayerName),
400 pDrView->IsLayerLocked(aLayerName),
401 pDrView->IsLayerPrintable(aLayerName)
402 ));
403 pManager->AddUndoAction( std::move(pAction) );
404 }
405
406 // First notify View since SetName() calls ResetActualLayer() and
407 // the View then already has to know the Layer
408 pView->SetActiveLayer(aNewName);
409 pLayer->SetName(aNewName);
410 rDoc.SetChanged();
411 }
412
ActivatePage()413 void LayerTabBar::ActivatePage()
414 {
415 if (pDrViewSh!=nullptr)
416 {
417
418 SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
419 pDispatcher->Execute(SID_SWITCHLAYER, SfxCallMode::ASYNCHRON);
420 }
421 }
422
SendActivatePageEvent()423 void LayerTabBar::SendActivatePageEvent()
424 {
425 CallEventListeners (VclEventId::TabbarPageActivated,
426 reinterpret_cast<void*>(GetCurPageId()));
427 }
428
SendDeactivatePageEvent()429 void LayerTabBar::SendDeactivatePageEvent()
430 {
431 CallEventListeners (VclEventId::TabbarPageDeactivated,
432 reinterpret_cast<void*>(GetCurPageId()));
433 }
434
435 } // end of namespace sd
436
437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
438