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 <com/sun/star/accessibility/AccessibleRelationType.hpp> 21 #include <com/sun/star/awt/XWindow.hpp> 22 #include <com/sun/star/awt/XWindowPeer.hpp> 23 #include <o3tl/sorted_vector.hxx> 24 #include <officecfg/Office/Common.hxx> 25 #include <iconview.hxx> 26 #include <salframe.hxx> 27 #include <salinst.hxx> 28 #include <salvd.hxx> 29 #include <salprn.hxx> 30 #include <saltimer.hxx> 31 #include <salsession.hxx> 32 #include <salsys.hxx> 33 #include <salbmp.hxx> 34 #include <salobj.hxx> 35 #include <salmenu.hxx> 36 #include <strings.hrc> 37 #include <svdata.hxx> 38 #include <svimpbox.hxx> 39 #include <messagedialog.hxx> 40 #include <treeglue.hxx> 41 #include <unotools/accessiblerelationsethelper.hxx> 42 #include <unotools/configmgr.hxx> 43 #include <utility> 44 #include <tools/helpers.hxx> 45 #include <vcl/abstdlg.hxx> 46 #include <vcl/builder.hxx> 47 #include <vcl/toolkit/combobox.hxx> 48 #include <vcl/toolkit/dialog.hxx> 49 #include <vcl/toolkit/fixed.hxx> 50 #include <vcl/toolkit/fixedhyper.hxx> 51 #include <vcl/toolkit/fmtfield.hxx> 52 #include <vcl/headbar.hxx> 53 #include <vcl/toolkit/ivctrl.hxx> 54 #include <vcl/layout.hxx> 55 #include <vcl/menubtn.hxx> 56 #include <vcl/toolkit/prgsbar.hxx> 57 #include <vcl/ptrstyle.hxx> 58 #include <slider.hxx> 59 #include <vcl/sysdata.hxx> 60 #include <vcl/toolkit/svlbitm.hxx> 61 #include <vcl/toolkit/svtabbx.hxx> 62 #include <vcl/tabctrl.hxx> 63 #include <vcl/tabpage.hxx> 64 #include <vcl/toolkit/treelistentry.hxx> 65 #include <vcl/toolkit/throbber.hxx> 66 #include <vcl/toolkit/unowrap.hxx> 67 #include <vcl/weld.hxx> 68 #include <vcl/weldutils.hxx> 69 #include <vcl/toolkit/vclmedit.hxx> 70 #include <vcl/toolkit/viewdataentry.hxx> 71 #include <vcl/virdev.hxx> 72 #include <bitmaps.hlst> 73 #include <calendar.hxx> 74 #include <verticaltabctrl.hxx> 75 #include <window.h> 76 #include <wizdlg.hxx> 77 #include <salvtables.hxx> 78 79 #include <boost/property_tree/ptree.hpp> 80 81 SalFrame::SalFrame() 82 : m_pWindow(nullptr) 83 , m_pProc(nullptr) 84 { 85 } 86 87 // this file contains the virtual destructors of the sal interface 88 // compilers usually put their vtables where the destructor is 89 90 SalFrame::~SalFrame() {} 91 92 void SalFrame::SetCallback(vcl::Window* pWindow, SALFRAMEPROC pProc) 93 { 94 m_pWindow = pWindow; 95 m_pProc = pProc; 96 } 97 98 // default to full-frame flushes 99 // on ports where partial-flushes are much cheaper this method should be overridden 100 void SalFrame::Flush(const tools::Rectangle&) { Flush(); } 101 102 void SalFrame::SetRepresentedURL(const OUString&) 103 { 104 // currently this is Mac only functionality 105 } 106 107 SalInstance::SalInstance(std::unique_ptr<comphelper::SolarMutex> pMutex) 108 : m_pYieldMutex(std::move(pMutex)) 109 { 110 } 111 112 SalInstance::~SalInstance() {} 113 114 comphelper::SolarMutex* SalInstance::GetYieldMutex() { return m_pYieldMutex.get(); } 115 116 sal_uInt32 SalInstance::ReleaseYieldMutexAll() { return m_pYieldMutex->release(true); } 117 118 void SalInstance::AcquireYieldMutex(sal_uInt32 nCount) { m_pYieldMutex->acquire(nCount); } 119 120 std::unique_ptr<SalSession> SalInstance::CreateSalSession() { return nullptr; } 121 122 std::unique_ptr<SalMenu> SalInstance::CreateMenu(bool, Menu*) 123 { 124 // default: no native menus 125 return nullptr; 126 } 127 128 std::unique_ptr<SalMenuItem> SalInstance::CreateMenuItem(const SalItemParams&) { return nullptr; } 129 130 bool SalInstance::CallEventCallback(void const* pEvent, int nBytes) 131 { 132 return m_pEventInst.is() && m_pEventInst->dispatchEvent(pEvent, nBytes); 133 } 134 135 SalTimer::~SalTimer() COVERITY_NOEXCEPT_FALSE {} 136 137 void SalBitmap::DropScaledCache() 138 { 139 if (ImplSVData* pSVData = ImplGetSVData()) 140 { 141 auto& rCache = pSVData->maGDIData.maScaleCache; 142 143 rCache.remove_if([this] (const lru_scale_cache::key_value_pair_t& rKeyValuePair) 144 { return rKeyValuePair.first.mpBitmap == this; }); 145 } 146 } 147 148 SalBitmap::~SalBitmap() { DropScaledCache(); } 149 150 SalSystem::~SalSystem() {} 151 152 SalPrinter::~SalPrinter() {} 153 154 bool SalPrinter::StartJob(const OUString*, const OUString&, const OUString&, ImplJobSetup*, 155 vcl::PrinterController&) 156 { 157 return false; 158 } 159 160 SalInfoPrinter::~SalInfoPrinter() {} 161 162 SalVirtualDevice::~SalVirtualDevice() {} 163 164 SalObject::~SalObject() {} 165 166 SalMenu::~SalMenu() {} 167 168 bool SalMenu::ShowNativePopupMenu(FloatingWindow*, const tools::Rectangle&, FloatWinPopupFlags) 169 { 170 return false; 171 } 172 173 void SalMenu::ShowCloseButton(bool) {} 174 175 bool SalMenu::AddMenuBarButton(const SalMenuButtonItem&) { return false; } 176 177 void SalMenu::RemoveMenuBarButton(sal_uInt16) {} 178 179 tools::Rectangle SalMenu::GetMenuBarButtonRectPixel(sal_uInt16, SalFrame*) 180 { 181 return tools::Rectangle(); 182 } 183 184 int SalMenu::GetMenuBarHeight() const { return 0; } 185 186 void SalMenu::ApplyPersona() {} 187 188 SalMenuItem::~SalMenuItem() {} 189 190 void SalInstanceWidget::ensure_event_listener() 191 { 192 if (!m_bEventListener) 193 { 194 m_xWidget->AddEventListener(LINK(this, SalInstanceWidget, EventListener)); 195 m_bEventListener = true; 196 } 197 } 198 199 // we want the ability to mark key events as handled, so use this variant 200 // for those, we get all keystrokes in this case, so we will need to filter 201 // them later 202 void SalInstanceWidget::ensure_key_listener() 203 { 204 if (!m_bKeyEventListener) 205 { 206 Application::AddKeyListener(LINK(this, SalInstanceWidget, KeyEventListener)); 207 m_bKeyEventListener = true; 208 } 209 } 210 211 // we want the ability to know about mouse events that happen in our children 212 // so use this variant, we will need to filter them later 213 void SalInstanceWidget::ensure_mouse_listener() 214 { 215 if (!m_bMouseEventListener) 216 { 217 Application::AddEventListener(LINK(this, SalInstanceWidget, MouseEventListener)); 218 m_bMouseEventListener = true; 219 } 220 } 221 222 void SalInstanceWidget::set_background(const Color& rColor) 223 { 224 m_xWidget->SetControlBackground(rColor); 225 m_xWidget->SetBackground(m_xWidget->GetControlBackground()); 226 // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under" 227 // transparent children of the widget 228 m_xWidget->SetStyle(m_xWidget->GetStyle() & ~WB_CLIPCHILDREN); 229 } 230 231 SalInstanceWidget::SalInstanceWidget(vcl::Window* pWidget, SalInstanceBuilder* pBuilder, 232 bool bTakeOwnership) 233 : m_xWidget(pWidget) 234 , m_pBuilder(pBuilder) 235 , m_bTakeOwnership(bTakeOwnership) 236 , m_bEventListener(false) 237 , m_bKeyEventListener(false) 238 , m_bMouseEventListener(false) 239 , m_nBlockNotify(0) 240 { 241 } 242 243 void SalInstanceWidget::set_sensitive(bool sensitive) { m_xWidget->Enable(sensitive); } 244 245 bool SalInstanceWidget::get_sensitive() const { return m_xWidget->IsEnabled(); } 246 247 bool SalInstanceWidget::get_visible() const { return m_xWidget->IsVisible(); } 248 249 bool SalInstanceWidget::is_visible() const { return m_xWidget->IsReallyVisible(); } 250 251 void SalInstanceWidget::set_can_focus(bool bCanFocus) 252 { 253 auto nStyle = m_xWidget->GetStyle() & ~(WB_TABSTOP | WB_NOTABSTOP); 254 if (bCanFocus) 255 nStyle |= WB_TABSTOP; 256 else 257 nStyle |= WB_NOTABSTOP; 258 m_xWidget->SetStyle(nStyle); 259 } 260 261 void SalInstanceWidget::grab_focus() 262 { 263 disable_notify_events(); 264 m_xWidget->GrabFocus(); 265 enable_notify_events(); 266 } 267 268 bool SalInstanceWidget::has_focus() const { return m_xWidget->HasFocus(); } 269 270 bool SalInstanceWidget::is_active() const { return m_xWidget->IsActive(); } 271 272 void SalInstanceWidget::set_has_default(bool has_default) 273 { 274 m_xWidget->set_property("has-default", OUString::boolean(has_default)); 275 } 276 277 bool SalInstanceWidget::get_has_default() const { return m_xWidget->GetStyle() & WB_DEFBUTTON; } 278 279 void SalInstanceWidget::show() { m_xWidget->Show(); } 280 281 void SalInstanceWidget::hide() { m_xWidget->Hide(); } 282 283 void SalInstanceWidget::set_size_request(int nWidth, int nHeight) 284 { 285 m_xWidget->set_width_request(nWidth); 286 m_xWidget->set_height_request(nHeight); 287 } 288 289 Size SalInstanceWidget::get_size_request() const 290 { 291 return Size(m_xWidget->get_width_request(), m_xWidget->get_height_request()); 292 } 293 294 Size SalInstanceWidget::get_preferred_size() const { return m_xWidget->get_preferred_size(); } 295 296 float SalInstanceWidget::get_approximate_digit_width() const 297 { 298 return m_xWidget->approximate_digit_width(); 299 } 300 301 int SalInstanceWidget::get_text_height() const { return m_xWidget->GetTextHeight(); } 302 303 Size SalInstanceWidget::get_pixel_size(const OUString& rText) const 304 { 305 //TODO, or do I want GetTextBoundRect ?, just using width at the moment anyway 306 return Size(m_xWidget->GetTextWidth(rText), m_xWidget->GetTextHeight()); 307 } 308 309 vcl::Font SalInstanceWidget::get_font() { return m_xWidget->GetPointFont(*m_xWidget); } 310 311 OString SalInstanceWidget::get_buildable_name() const { return m_xWidget->get_id().toUtf8(); } 312 313 void SalInstanceWidget::set_help_id(const OString& rId) { return m_xWidget->SetHelpId(rId); } 314 315 OString SalInstanceWidget::get_help_id() const { return m_xWidget->GetHelpId(); } 316 317 void SalInstanceWidget::set_grid_left_attach(int nAttach) 318 { 319 m_xWidget->set_grid_left_attach(nAttach); 320 } 321 322 int SalInstanceWidget::get_grid_left_attach() const { return m_xWidget->get_grid_left_attach(); } 323 324 void SalInstanceWidget::set_grid_width(int nCols) { m_xWidget->set_grid_width(nCols); } 325 326 void SalInstanceWidget::set_grid_top_attach(int nAttach) 327 { 328 m_xWidget->set_grid_top_attach(nAttach); 329 } 330 331 int SalInstanceWidget::get_grid_top_attach() const { return m_xWidget->get_grid_top_attach(); } 332 333 void SalInstanceWidget::set_hexpand(bool bExpand) { m_xWidget->set_hexpand(bExpand); } 334 335 bool SalInstanceWidget::get_hexpand() const { return m_xWidget->get_hexpand(); } 336 337 void SalInstanceWidget::set_vexpand(bool bExpand) { m_xWidget->set_vexpand(bExpand); } 338 339 bool SalInstanceWidget::get_vexpand() const { return m_xWidget->get_vexpand(); } 340 341 void SalInstanceWidget::set_secondary(bool bSecondary) { m_xWidget->set_secondary(bSecondary); } 342 343 void SalInstanceWidget::set_margin_top(int nMargin) { m_xWidget->set_margin_top(nMargin); } 344 345 void SalInstanceWidget::set_margin_bottom(int nMargin) { m_xWidget->set_margin_bottom(nMargin); } 346 347 void SalInstanceWidget::set_margin_left(int nMargin) { m_xWidget->set_margin_left(nMargin); } 348 349 void SalInstanceWidget::set_margin_right(int nMargin) { m_xWidget->set_margin_bottom(nMargin); } 350 351 int SalInstanceWidget::get_margin_top() const { return m_xWidget->get_margin_top(); } 352 353 int SalInstanceWidget::get_margin_bottom() const { return m_xWidget->get_margin_bottom(); } 354 355 int SalInstanceWidget::get_margin_left() const { return m_xWidget->get_margin_left(); } 356 357 int SalInstanceWidget::get_margin_right() const { return m_xWidget->get_margin_bottom(); } 358 359 void SalInstanceWidget::set_accessible_name(const OUString& rName) 360 { 361 m_xWidget->SetAccessibleName(rName); 362 } 363 364 OUString SalInstanceWidget::get_accessible_name() const { return m_xWidget->GetAccessibleName(); } 365 366 OUString SalInstanceWidget::get_accessible_description() const 367 { 368 return m_xWidget->GetAccessibleDescription(); 369 } 370 371 void SalInstanceWidget::set_accessible_relation_labeled_by(weld::Widget* pLabel) 372 { 373 vcl::Window* pAtkLabel 374 = pLabel ? dynamic_cast<SalInstanceWidget&>(*pLabel).getWidget() : nullptr; 375 m_xWidget->SetAccessibleRelationLabeledBy(pAtkLabel); 376 } 377 378 void SalInstanceWidget::set_accessible_relation_label_for(weld::Widget* pLabeled) 379 { 380 vcl::Window* pAtkLabeled 381 = pLabeled ? dynamic_cast<SalInstanceWidget&>(*pLabeled).getWidget() : nullptr; 382 m_xWidget->SetAccessibleRelationLabelFor(pAtkLabeled); 383 } 384 385 void SalInstanceWidget::set_tooltip_text(const OUString& rTip) 386 { 387 m_xWidget->SetQuickHelpText(rTip); 388 } 389 390 OUString SalInstanceWidget::get_tooltip_text() const { return m_xWidget->GetQuickHelpText(); } 391 392 void SalInstanceWidget::connect_focus_in(const Link<Widget&, void>& rLink) 393 { 394 ensure_event_listener(); 395 weld::Widget::connect_focus_in(rLink); 396 } 397 398 void SalInstanceWidget::connect_mnemonic_activate(const Link<Widget&, bool>& rLink) 399 { 400 m_xWidget->SetMnemonicActivateHdl(LINK(this, SalInstanceWidget, MnemonicActivateHdl)); 401 weld::Widget::connect_mnemonic_activate(rLink); 402 } 403 404 void SalInstanceWidget::connect_focus_out(const Link<Widget&, void>& rLink) 405 { 406 ensure_event_listener(); 407 weld::Widget::connect_focus_out(rLink); 408 } 409 410 void SalInstanceWidget::connect_size_allocate(const Link<const Size&, void>& rLink) 411 { 412 ensure_event_listener(); 413 weld::Widget::connect_size_allocate(rLink); 414 } 415 416 void SalInstanceWidget::connect_mouse_press(const Link<const MouseEvent&, bool>& rLink) 417 { 418 ensure_mouse_listener(); 419 weld::Widget::connect_mouse_press(rLink); 420 } 421 422 void SalInstanceWidget::connect_mouse_move(const Link<const MouseEvent&, bool>& rLink) 423 { 424 ensure_mouse_listener(); 425 weld::Widget::connect_mouse_move(rLink); 426 } 427 428 void SalInstanceWidget::connect_mouse_release(const Link<const MouseEvent&, bool>& rLink) 429 { 430 ensure_mouse_listener(); 431 weld::Widget::connect_mouse_release(rLink); 432 } 433 434 void SalInstanceWidget::connect_key_press(const Link<const KeyEvent&, bool>& rLink) 435 { 436 ensure_key_listener(); 437 weld::Widget::connect_key_press(rLink); 438 } 439 440 void SalInstanceWidget::connect_key_release(const Link<const KeyEvent&, bool>& rLink) 441 { 442 ensure_key_listener(); 443 weld::Widget::connect_key_release(rLink); 444 } 445 446 bool SalInstanceWidget::get_extents_relative_to(const Widget& rRelative, int& x, int& y, int& width, 447 int& height) const 448 { 449 tools::Rectangle aRect(m_xWidget->GetWindowExtentsRelative( 450 dynamic_cast<const SalInstanceWidget&>(rRelative).getWidget())); 451 x = aRect.Left(); 452 y = aRect.Top(); 453 width = aRect.GetWidth(); 454 height = aRect.GetHeight(); 455 return true; 456 } 457 458 void SalInstanceWidget::grab_add() { m_xWidget->CaptureMouse(); } 459 460 bool SalInstanceWidget::has_grab() const { return m_xWidget->IsMouseCaptured(); } 461 462 void SalInstanceWidget::grab_remove() { m_xWidget->ReleaseMouse(); } 463 464 bool SalInstanceWidget::get_direction() const { return m_xWidget->IsRTLEnabled(); } 465 466 void SalInstanceWidget::set_direction(bool bRTL) { m_xWidget->EnableRTL(bRTL); } 467 468 void SalInstanceWidget::freeze() { m_xWidget->SetUpdateMode(false); } 469 470 void SalInstanceWidget::thaw() { m_xWidget->SetUpdateMode(true); } 471 472 SalInstanceWidget::~SalInstanceWidget() 473 { 474 if (m_aMnemonicActivateHdl.IsSet()) 475 m_xWidget->SetMnemonicActivateHdl(Link<vcl::Window&, bool>()); 476 if (m_bMouseEventListener) 477 Application::RemoveEventListener(LINK(this, SalInstanceWidget, MouseEventListener)); 478 if (m_bKeyEventListener) 479 Application::RemoveKeyListener(LINK(this, SalInstanceWidget, KeyEventListener)); 480 if (m_bEventListener) 481 m_xWidget->RemoveEventListener(LINK(this, SalInstanceWidget, EventListener)); 482 if (m_bTakeOwnership) 483 m_xWidget.disposeAndClear(); 484 } 485 486 vcl::Window* SalInstanceWidget::getWidget() const { return m_xWidget; } 487 488 void SalInstanceWidget::disable_notify_events() { ++m_nBlockNotify; } 489 490 bool SalInstanceWidget::notify_events_disabled() { return m_nBlockNotify != 0; } 491 492 void SalInstanceWidget::enable_notify_events() { --m_nBlockNotify; } 493 494 OUString SalInstanceWidget::strip_mnemonic(const OUString& rLabel) const 495 { 496 return rLabel.replaceFirst("~", ""); 497 } 498 499 VclPtr<VirtualDevice> SalInstanceWidget::create_virtual_device() const 500 { 501 // create with (annoying) separate alpha layer that LibreOffice itself uses 502 return VclPtr<VirtualDevice>::Create(*Application::GetDefaultDevice(), DeviceFormat::DEFAULT, 503 DeviceFormat::DEFAULT); 504 } 505 506 css::uno::Reference<css::datatransfer::dnd::XDropTarget> SalInstanceWidget::get_drop_target() 507 { 508 return m_xWidget->GetDropTarget(); 509 } 510 511 void SalInstanceWidget::connect_get_property_tree( 512 const Link<tools::JsonWriter&, void>& rLink) 513 { 514 m_xWidget->SetDumpAsPropertyTreeHdl(rLink); 515 } 516 517 void SalInstanceWidget::set_stack_background() 518 { 519 set_background(m_xWidget->GetSettings().GetStyleSettings().GetWindowColor()); 520 } 521 522 void SalInstanceWidget::set_title_background() 523 { 524 set_background(m_xWidget->GetSettings().GetStyleSettings().GetShadowColor()); 525 } 526 527 void SalInstanceWidget::set_toolbar_background() 528 { 529 m_xWidget->SetBackground(); 530 m_xWidget->SetPaintTransparent(true); 531 } 532 533 void SalInstanceWidget::set_highlight_background() 534 { 535 set_background(m_xWidget->GetSettings().GetStyleSettings().GetHighlightColor()); 536 } 537 538 SystemWindow* SalInstanceWidget::getSystemWindow() { return m_xWidget->GetSystemWindow(); } 539 540 void SalInstanceWidget::HandleEventListener(VclWindowEvent& rEvent) 541 { 542 if (notify_events_disabled()) 543 return; 544 if (rEvent.GetId() == VclEventId::WindowGetFocus) 545 m_aFocusInHdl.Call(*this); 546 else if (rEvent.GetId() == VclEventId::WindowLoseFocus) 547 m_aFocusOutHdl.Call(*this); 548 else if (rEvent.GetId() == VclEventId::WindowResize) 549 m_aSizeAllocateHdl.Call(m_xWidget->GetSizePixel()); 550 } 551 552 namespace 553 { 554 MouseEvent TransformEvent(const MouseEvent& rEvent, const vcl::Window* pParent, const vcl::Window* pChild) 555 { 556 return MouseEvent(pParent->ScreenToOutputPixel(pChild->OutputToScreenPixel(rEvent.GetPosPixel())), 557 rEvent.GetClicks(), rEvent.GetMode(), rEvent.GetButtons(), rEvent.GetModifier()); 558 } 559 } 560 561 void SalInstanceWidget::HandleMouseEventListener(VclSimpleEvent& rEvent) 562 { 563 if (rEvent.GetId() == VclEventId::WindowMouseButtonDown) 564 { 565 auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent); 566 if (m_xWidget == rWinEvent.GetWindow()) 567 { 568 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData()); 569 m_aMousePressHdl.Call(*pMouseEvent); 570 } 571 else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow())) 572 { 573 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData()); 574 const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow())); 575 m_aMousePressHdl.Call(aTransformedEvent); 576 } 577 } 578 else if (rEvent.GetId() == VclEventId::WindowMouseButtonUp) 579 { 580 auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent); 581 if (m_xWidget == rWinEvent.GetWindow()) 582 { 583 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData()); 584 m_aMouseReleaseHdl.Call(*pMouseEvent); 585 } 586 else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow())) 587 { 588 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData()); 589 const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow())); 590 m_aMouseReleaseHdl.Call(aTransformedEvent); 591 } 592 } 593 else if (rEvent.GetId() == VclEventId::WindowMouseMove) 594 { 595 auto& rWinEvent = static_cast<VclWindowEvent&>(rEvent); 596 if (m_xWidget == rWinEvent.GetWindow()) 597 { 598 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData()); 599 m_aMouseMotionHdl.Call(*pMouseEvent); 600 } 601 else if (m_xWidget->ImplIsChild(rWinEvent.GetWindow())) 602 { 603 const MouseEvent* pMouseEvent = static_cast<const MouseEvent*>(rWinEvent.GetData()); 604 const MouseEvent aTransformedEvent(TransformEvent(*pMouseEvent, m_xWidget, rWinEvent.GetWindow())); 605 m_aMouseMotionHdl.Call(aTransformedEvent); 606 } 607 } 608 } 609 610 bool SalInstanceWidget::HandleKeyEventListener(VclWindowEvent& rEvent) 611 { 612 // we get all key events here, ignore them unless we have focus 613 if (!m_xWidget->HasChildPathFocus()) 614 return false; 615 if (rEvent.GetId() == VclEventId::WindowKeyInput) 616 { 617 const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData()); 618 return m_aKeyPressHdl.Call(*pKeyEvent); 619 } 620 else if (rEvent.GetId() == VclEventId::WindowKeyUp) 621 { 622 const KeyEvent* pKeyEvent = static_cast<const KeyEvent*>(rEvent.GetData()); 623 return m_aKeyReleaseHdl.Call(*pKeyEvent); 624 } 625 return false; 626 } 627 628 IMPL_LINK(SalInstanceWidget, EventListener, VclWindowEvent&, rEvent, void) 629 { 630 HandleEventListener(rEvent); 631 } 632 633 IMPL_LINK(SalInstanceWidget, KeyEventListener, VclWindowEvent&, rEvent, bool) 634 { 635 return HandleKeyEventListener(rEvent); 636 } 637 638 IMPL_LINK(SalInstanceWidget, MouseEventListener, VclSimpleEvent&, rEvent, void) 639 { 640 HandleMouseEventListener(rEvent); 641 } 642 643 IMPL_LINK_NOARG(SalInstanceWidget, MnemonicActivateHdl, vcl::Window&, bool) 644 { 645 return m_aMnemonicActivateHdl.Call(*this); 646 } 647 648 namespace 649 { 650 Image createImage(const OUString& rImage) 651 { 652 if (rImage.isEmpty()) 653 return Image(); 654 if (rImage.lastIndexOf('.') != rImage.getLength() - 4) 655 { 656 assert((rImage == "dialog-warning" || rImage == "dialog-error" 657 || rImage == "dialog-information") 658 && "unknown stock image"); 659 if (rImage == "dialog-warning") 660 return Image(StockImage::Yes, IMG_WARN); 661 else if (rImage == "dialog-error") 662 return Image(StockImage::Yes, IMG_ERROR); 663 else if (rImage == "dialog-information") 664 return Image(StockImage::Yes, IMG_INFO); 665 } 666 return Image(StockImage::Yes, rImage); 667 } 668 669 Image createImage(const VirtualDevice& rDevice) 670 { 671 return Image(rDevice.GetBitmapEx(Point(), rDevice.GetOutputSizePixel())); 672 } 673 674 sal_uInt16 insert_to_menu(sal_uInt16 nLastId, PopupMenu* pMenu, int pos, const OUString& rId, 675 const OUString& rStr, const OUString* pIconName, 676 const VirtualDevice* pImageSurface, TriState eCheckRadioFalse) 677 { 678 const sal_uInt16 nNewid = nLastId + 1; 679 680 MenuItemBits nBits; 681 if (eCheckRadioFalse == TRISTATE_TRUE) 682 nBits = MenuItemBits::CHECKABLE; 683 else if (eCheckRadioFalse == TRISTATE_FALSE) 684 nBits = MenuItemBits::CHECKABLE | MenuItemBits::RADIOCHECK; 685 else 686 nBits = MenuItemBits::NONE; 687 688 pMenu->InsertItem(nNewid, rStr, nBits, 689 OUStringToOString(rId, RTL_TEXTENCODING_UTF8), pos == -1 ? MENU_APPEND : pos); 690 if (pIconName) 691 { 692 pMenu->SetItemImage(nNewid, createImage(*pIconName)); 693 } 694 else if (pImageSurface) 695 { 696 pMenu->SetItemImage(nNewid, createImage(*pImageSurface)); 697 } 698 return nNewid; 699 } 700 } 701 702 SalInstanceMenu::SalInstanceMenu(PopupMenu* pMenu, bool bTakeOwnership) 703 : m_xMenu(pMenu) 704 , m_bTakeOwnership(bTakeOwnership) 705 { 706 const auto nCount = m_xMenu->GetItemCount(); 707 m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0; 708 m_xMenu->SetSelectHdl(LINK(this, SalInstanceMenu, SelectMenuHdl)); 709 } 710 OString SalInstanceMenu::popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect) 711 { 712 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent); 713 assert(pVclWidget); 714 m_xMenu->Execute(pVclWidget->getWidget(), rRect, 715 PopupMenuFlags::ExecuteDown | PopupMenuFlags::NoMouseUpClose); 716 return m_xMenu->GetCurItemIdent(); 717 } 718 void SalInstanceMenu::set_sensitive(const OString& rIdent, bool bSensitive) 719 { 720 m_xMenu->EnableItem(rIdent, bSensitive); 721 } 722 void SalInstanceMenu::set_active(const OString& rIdent, bool bActive) 723 { 724 m_xMenu->CheckItem(rIdent, bActive); 725 } 726 bool SalInstanceMenu::get_active(const OString& rIdent) const 727 { 728 return m_xMenu->IsItemChecked(m_xMenu->GetItemId(rIdent)); 729 } 730 void SalInstanceMenu::set_label(const OString& rIdent, const OUString& rLabel) 731 { 732 m_xMenu->SetItemText(m_xMenu->GetItemId(rIdent), rLabel); 733 } 734 OUString SalInstanceMenu::get_label(const OString& rIdent) const 735 { 736 return m_xMenu->GetItemText(m_xMenu->GetItemId(rIdent)); 737 } 738 void SalInstanceMenu::set_visible(const OString& rIdent, bool bShow) 739 { 740 m_xMenu->ShowItem(m_xMenu->GetItemId(rIdent), bShow); 741 } 742 void SalInstanceMenu::clear() { m_xMenu->Clear(); } 743 void SalInstanceMenu::insert(int pos, const OUString& rId, const OUString& rStr, 744 const OUString* pIconName, VirtualDevice* pImageSurface, 745 TriState eCheckRadioFalse) 746 { 747 m_nLastId 748 = insert_to_menu(m_nLastId, m_xMenu, pos, rId, rStr, pIconName, pImageSurface, eCheckRadioFalse); 749 } 750 void SalInstanceMenu::insert_separator(int pos, const OUString& rId) 751 { 752 auto nInsertPos = pos == -1 ? MENU_APPEND : pos; 753 m_xMenu->InsertSeparator(rId.toUtf8(), nInsertPos); 754 } 755 void SalInstanceMenu::remove(const OString& rId) 756 { 757 m_xMenu->RemoveItem(m_xMenu->GetItemPos(m_xMenu->GetItemId(rId))); 758 } 759 int SalInstanceMenu::n_children() const { return m_xMenu->GetItemCount(); } 760 PopupMenu* SalInstanceMenu::getMenu() const { return m_xMenu.get(); } 761 SalInstanceMenu::~SalInstanceMenu() 762 { 763 m_xMenu->SetSelectHdl(Link<::Menu*, bool>()); 764 if (m_bTakeOwnership) 765 m_xMenu.disposeAndClear(); 766 } 767 768 IMPL_LINK_NOARG(SalInstanceMenu, SelectMenuHdl, ::Menu*, bool) 769 { 770 signal_activate(m_xMenu->GetCurItemIdent()); 771 /* tdf#131333 Menu::Select depends on a false here to allow 772 propagating a submens's selected id to its parent menu to become its 773 selected id. 774 775 without this, while gen menus already have propagated this to its parent 776 in MenuFloatingWindow::EndExecute, SalMenus as used under kf5/macOS 777 won't propagate the selected id 778 */ 779 return false; 780 } 781 782 SalInstanceToolbar::SalInstanceToolbar(ToolBox* pToolBox, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 783 : SalInstanceWidget(pToolBox, pBuilder, bTakeOwnership) 784 , m_xToolBox(pToolBox) 785 { 786 m_xToolBox->SetSelectHdl(LINK(this, SalInstanceToolbar, ClickHdl)); 787 m_xToolBox->SetDropdownClickHdl(LINK(this, SalInstanceToolbar, DropdownClick)); 788 } 789 790 void SalInstanceToolbar::set_item_sensitive(const OString& rIdent, bool bSensitive) 791 { 792 m_xToolBox->EnableItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bSensitive); 793 } 794 795 bool SalInstanceToolbar::get_item_sensitive(const OString& rIdent) const 796 { 797 return m_xToolBox->IsItemEnabled(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent))); 798 } 799 800 void SalInstanceToolbar::set_item_visible(const OString& rIdent, bool bVisible) 801 { 802 m_xToolBox->ShowItem(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), bVisible); 803 } 804 805 void SalInstanceToolbar::set_item_help_id(const OString& rIdent, const OString& rHelpId) 806 { 807 m_xToolBox->SetHelpId(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rHelpId); 808 } 809 810 bool SalInstanceToolbar::get_item_visible(const OString& rIdent) const 811 { 812 return m_xToolBox->IsItemVisible(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent))); 813 } 814 815 void SalInstanceToolbar::set_item_active(const OString& rIdent, bool bActive) 816 { 817 sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)); 818 m_xToolBox->CheckItem(nItemId, bActive); 819 } 820 821 bool SalInstanceToolbar::get_item_active(const OString& rIdent) const 822 { 823 return m_xToolBox->IsItemChecked(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent))); 824 } 825 826 void SalInstanceToolbar::set_menu_item_active(const OString& rIdent, bool bActive) 827 { 828 sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)); 829 assert(m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN); 830 831 if (bActive) 832 { 833 m_sStartShowIdent = m_xToolBox->GetItemCommand(nItemId).toUtf8(); 834 signal_toggle_menu(m_sStartShowIdent); 835 } 836 837 auto pFloat = m_aFloats[nItemId]; 838 if (pFloat) 839 { 840 if (bActive) 841 vcl::Window::GetDockingManager()->StartPopupMode(m_xToolBox, pFloat, 842 FloatWinPopupFlags::GrabFocus); 843 else 844 vcl::Window::GetDockingManager()->EndPopupMode(pFloat); 845 } 846 auto pPopup = m_aMenus[nItemId]; 847 if (pPopup) 848 { 849 if (bActive) 850 { 851 tools::Rectangle aRect = m_xToolBox->GetItemRect(nItemId); 852 pPopup->Execute(m_xToolBox, aRect, PopupMenuFlags::ExecuteDown); 853 } 854 else 855 pPopup->EndExecute(); 856 } 857 858 m_sStartShowIdent.clear(); 859 } 860 861 bool SalInstanceToolbar::get_menu_item_active(const OString& rIdent) const 862 { 863 sal_uInt16 nItemId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)); 864 assert(m_xToolBox->GetItemBits(nItemId) & ToolBoxItemBits::DROPDOWN); 865 866 if (rIdent == m_sStartShowIdent) 867 return true; 868 869 auto aFloat = m_aFloats.find(nItemId); 870 if (aFloat != m_aFloats.end()) 871 { 872 return vcl::Window::GetDockingManager()->IsInPopupMode(aFloat->second); 873 } 874 875 auto aPopup = m_aMenus.find(nItemId); 876 if (aPopup != m_aMenus.end()) 877 { 878 return PopupMenu::GetActivePopupMenu() == aPopup->second; 879 } 880 881 return false; 882 } 883 884 void SalInstanceToolbar::set_item_popover(const OString& rIdent, weld::Widget* pPopover) 885 { 886 SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover); 887 888 vcl::Window* pFloat = pPopoverWidget ? pPopoverWidget->getWidget() : nullptr; 889 if (pFloat) 890 { 891 pFloat->AddEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener)); 892 pFloat->EnableDocking(); 893 } 894 895 sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)); 896 auto xOldFloat = m_aFloats[nId]; 897 if (xOldFloat) 898 { 899 xOldFloat->RemoveEventListener(LINK(this, SalInstanceToolbar, MenuToggleListener)); 900 } 901 m_aFloats[nId] = pFloat; 902 m_aMenus[nId] = nullptr; 903 } 904 905 void SalInstanceToolbar::set_item_menu(const OString& rIdent, weld::Menu* pMenu) 906 { 907 SalInstanceMenu* pInstanceMenu = dynamic_cast<SalInstanceMenu*>(pMenu); 908 909 PopupMenu* pPopup = pInstanceMenu ? pInstanceMenu->getMenu() : nullptr; 910 911 sal_uInt16 nId = m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)); 912 m_aMenus[nId] = pPopup; 913 m_aFloats[nId] = nullptr; 914 } 915 916 void SalInstanceToolbar::insert_separator(int pos, const OUString& /*rId*/) 917 { 918 auto nInsertPos = pos == -1 ? ToolBox::APPEND : pos; 919 m_xToolBox->InsertSeparator(nInsertPos, 5); 920 } 921 922 int SalInstanceToolbar::get_n_items() const { return m_xToolBox->GetItemCount(); } 923 924 OString SalInstanceToolbar::get_item_ident(int nIndex) const 925 { 926 return m_xToolBox->GetItemCommand(m_xToolBox->GetItemId(nIndex)).toUtf8(); 927 } 928 929 void SalInstanceToolbar::set_item_ident(int nIndex, const OString& rIdent) 930 { 931 return m_xToolBox->SetItemCommand(m_xToolBox->GetItemId(nIndex), 932 OUString::fromUtf8(rIdent)); 933 } 934 935 void SalInstanceToolbar::set_item_label(int nIndex, const OUString& rLabel) 936 { 937 m_xToolBox->SetItemText(m_xToolBox->GetItemId(nIndex), rLabel); 938 } 939 940 OUString SalInstanceToolbar::get_item_label(const OString& rIdent) const 941 { 942 return m_xToolBox->GetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent))); 943 } 944 945 void SalInstanceToolbar::set_item_label(const OString& rIdent, const OUString& rLabel) 946 { 947 m_xToolBox->SetItemText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rLabel); 948 } 949 950 void SalInstanceToolbar::set_item_icon_name(const OString& rIdent, const OUString& rIconName) 951 { 952 m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), 953 Image(StockImage::Yes, rIconName)); 954 } 955 956 void SalInstanceToolbar::set_item_image(const OString& rIdent, 957 const css::uno::Reference<css::graphic::XGraphic>& rIcon) 958 { 959 m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image(rIcon)); 960 } 961 962 void SalInstanceToolbar::set_item_image(const OString& rIdent, VirtualDevice* pDevice) 963 { 964 if (pDevice) 965 m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), 966 createImage(*pDevice)); 967 else 968 m_xToolBox->SetItemImage(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), Image()); 969 } 970 971 void SalInstanceToolbar::set_item_image(int nIndex, 972 const css::uno::Reference<css::graphic::XGraphic>& rIcon) 973 { 974 m_xToolBox->SetItemImage(m_xToolBox->GetItemId(nIndex), Image(rIcon)); 975 } 976 977 void SalInstanceToolbar::set_item_tooltip_text(int nIndex, const OUString& rTip) 978 { 979 m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(nIndex), rTip); 980 } 981 982 void SalInstanceToolbar::set_item_tooltip_text(const OString& rIdent, const OUString& rTip) 983 { 984 m_xToolBox->SetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent)), rTip); 985 } 986 987 OUString SalInstanceToolbar::get_item_tooltip_text(const OString& rIdent) const 988 { 989 return m_xToolBox->GetQuickHelpText(m_xToolBox->GetItemId(OUString::fromUtf8(rIdent))); 990 } 991 992 vcl::ImageType SalInstanceToolbar::get_icon_size() const { return m_xToolBox->GetImageSize(); } 993 994 void SalInstanceToolbar::set_icon_size(vcl::ImageType eType) 995 { 996 ToolBoxButtonSize eButtonSize = ToolBoxButtonSize::DontCare; 997 switch (eType) 998 { 999 case vcl::ImageType::Size16: 1000 eButtonSize = ToolBoxButtonSize::Small; 1001 break; 1002 case vcl::ImageType::Size26: 1003 eButtonSize = ToolBoxButtonSize::Large; 1004 break; 1005 case vcl::ImageType::Size32: 1006 eButtonSize = ToolBoxButtonSize::Size32; 1007 break; 1008 } 1009 if (m_xToolBox->GetToolboxButtonSize() != eButtonSize) 1010 { 1011 m_xToolBox->SetToolboxButtonSize(eButtonSize); 1012 m_xToolBox->queue_resize(); 1013 } 1014 } 1015 1016 sal_uInt16 SalInstanceToolbar::get_modifier_state() const 1017 { 1018 return m_xToolBox->GetModifier(); 1019 } 1020 1021 int SalInstanceToolbar::get_drop_index(const Point& rPoint) const 1022 { 1023 auto nRet = m_xToolBox->GetItemPos(rPoint); 1024 if (nRet == ToolBox::ITEM_NOTFOUND) 1025 return 0; 1026 return nRet; 1027 } 1028 1029 SalInstanceToolbar::~SalInstanceToolbar() 1030 { 1031 m_xToolBox->SetDropdownClickHdl(Link<ToolBox*, void>()); 1032 m_xToolBox->SetSelectHdl(Link<ToolBox*, void>()); 1033 } 1034 1035 IMPL_LINK_NOARG(SalInstanceToolbar, ClickHdl, ToolBox*, void) 1036 { 1037 sal_uInt16 nItemId = m_xToolBox->GetCurItemId(); 1038 signal_clicked(m_xToolBox->GetItemCommand(nItemId).toUtf8()); 1039 } 1040 1041 IMPL_LINK_NOARG(SalInstanceToolbar, DropdownClick, ToolBox*, void) 1042 { 1043 sal_uInt16 nItemId = m_xToolBox->GetCurItemId(); 1044 set_menu_item_active(m_xToolBox->GetItemCommand(nItemId).toUtf8(), true); 1045 } 1046 1047 IMPL_LINK(SalInstanceToolbar, MenuToggleListener, VclWindowEvent&, rEvent, void) 1048 { 1049 if (rEvent.GetId() == VclEventId::WindowEndPopupMode) 1050 { 1051 for (auto& rFloat : m_aFloats) 1052 { 1053 if (rEvent.GetWindow() == rFloat.second) 1054 { 1055 sal_uInt16 nItemId = rFloat.first; 1056 signal_toggle_menu(m_xToolBox->GetItemCommand(nItemId).toUtf8()); 1057 break; 1058 } 1059 } 1060 } 1061 } 1062 1063 namespace 1064 { 1065 class SalInstanceSizeGroup : public weld::SizeGroup 1066 { 1067 private: 1068 std::shared_ptr<VclSizeGroup> m_xGroup; 1069 1070 public: 1071 SalInstanceSizeGroup() 1072 : m_xGroup(std::make_shared<VclSizeGroup>()) 1073 { 1074 } 1075 virtual void add_widget(weld::Widget* pWidget) override 1076 { 1077 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget); 1078 assert(pVclWidget && pVclWidget->getWidget()); 1079 pVclWidget->getWidget()->add_to_size_group(m_xGroup); 1080 } 1081 virtual void set_mode(VclSizeGroupMode eMode) override { m_xGroup->set_mode(eMode); } 1082 }; 1083 } 1084 1085 void SalInstanceContainer::implResetDefault(const vcl::Window* _pWindow) 1086 { 1087 vcl::Window* pChildLoop = _pWindow->GetWindow(GetWindowType::FirstChild); 1088 while (pChildLoop) 1089 { 1090 // does the window participate in the tabbing order? 1091 if (pChildLoop->GetStyle() & WB_DIALOGCONTROL) 1092 implResetDefault(pChildLoop); 1093 1094 // is it a button? 1095 WindowType eType = pChildLoop->GetType(); 1096 if ((WindowType::PUSHBUTTON == eType) || (WindowType::OKBUTTON == eType) 1097 || (WindowType::CANCELBUTTON == eType) || (WindowType::HELPBUTTON == eType) 1098 || (WindowType::IMAGEBUTTON == eType) || (WindowType::MENUBUTTON == eType) 1099 || (WindowType::MOREBUTTON == eType)) 1100 { 1101 pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON); 1102 } 1103 1104 // the next one ... 1105 pChildLoop = pChildLoop->GetWindow(GetWindowType::Next); 1106 } 1107 } 1108 1109 SalInstanceContainer::SalInstanceContainer(vcl::Window* pContainer, SalInstanceBuilder* pBuilder, 1110 bool bTakeOwnership) 1111 : SalInstanceWidget(pContainer, pBuilder, bTakeOwnership) 1112 , m_xContainer(pContainer) 1113 { 1114 } 1115 1116 void SalInstanceContainer::move(weld::Widget* pWidget, weld::Container* pNewParent) 1117 { 1118 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget); 1119 assert(pVclWidget); 1120 SalInstanceContainer* pNewVclParent = dynamic_cast<SalInstanceContainer*>(pNewParent); 1121 assert(!pNewParent || pNewVclParent); 1122 if (pNewVclParent) 1123 pVclWidget->getWidget()->SetParent(pNewVclParent->getWidget()); 1124 else 1125 pVclWidget->getWidget()->SetParentToDefaultWindow(); 1126 } 1127 1128 void SalInstanceContainer::recursively_unset_default_buttons() 1129 { 1130 implResetDefault(m_xContainer.get()); 1131 } 1132 1133 css::uno::Reference<css::awt::XWindow> SalInstanceContainer::CreateChildFrame() 1134 { 1135 auto xPage = VclPtr<VclBin>::Create(m_xContainer.get()); 1136 xPage->set_expand(true); 1137 xPage->Show(); 1138 return css::uno::Reference<css::awt::XWindow>(xPage->GetComponentInterface(), 1139 css::uno::UNO_QUERY); 1140 } 1141 1142 std::unique_ptr<weld::Container> SalInstanceWidget::weld_parent() const 1143 { 1144 vcl::Window* pParent = m_xWidget->GetParent(); 1145 if (!pParent) 1146 return nullptr; 1147 return std::make_unique<SalInstanceContainer>(pParent, m_pBuilder, false); 1148 } 1149 1150 namespace 1151 { 1152 void DoRecursivePaint(vcl::Window* pWindow, const Point& rPos, OutputDevice& rOutput) 1153 { 1154 Size aSize = pWindow->GetSizePixel(); 1155 1156 VclPtr<VirtualDevice> xOutput(VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT)); 1157 xOutput->SetOutputSizePixel(aSize); 1158 xOutput->DrawOutDev(Point(), aSize, rPos, aSize, rOutput); 1159 1160 //set ReallyVisible to match Visible, we restore the original 1161 //state after Paint 1162 WindowImpl* pImpl = pWindow->ImplGetWindowImpl(); 1163 bool bRVisible = pImpl->mbReallyVisible; 1164 pImpl->mbReallyVisible = pWindow->IsVisible(); 1165 1166 pWindow->Paint(*xOutput, tools::Rectangle(Point(), aSize)); 1167 1168 pImpl->mbReallyVisible = bRVisible; 1169 1170 rOutput.DrawOutDev(rPos, aSize, Point(), aSize, *xOutput); 1171 1172 xOutput.disposeAndClear(); 1173 1174 for (vcl::Window *pChild = pWindow->GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next)) 1175 { 1176 if (!pChild->IsVisible()) 1177 continue; 1178 DoRecursivePaint(pChild, rPos + pChild->GetPosPixel(), rOutput); 1179 } 1180 } 1181 } 1182 1183 void SalInstanceWidget::draw(OutputDevice& rOutput, const tools::Rectangle& rRect) 1184 { 1185 Size aOrigSize(m_xWidget->GetSizePixel()); 1186 1187 m_xWidget->SetSizePixel(rRect.GetSize()); 1188 DoRecursivePaint(m_xWidget, rRect.TopLeft(), rOutput); 1189 1190 m_xWidget->SetSizePixel(aOrigSize); 1191 } 1192 1193 namespace 1194 { 1195 class SalInstanceBox : public SalInstanceContainer, public virtual weld::Box 1196 { 1197 private: 1198 VclPtr<VclBox> m_xBox; 1199 public: 1200 SalInstanceBox(VclBox* pContainer, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 1201 : SalInstanceContainer(pContainer, pBuilder, bTakeOwnership) 1202 , m_xBox(pContainer) 1203 { 1204 } 1205 virtual void reorder_child(weld::Widget* pWidget, int nNewPosition) override 1206 { 1207 SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pWidget); 1208 assert(pVclWidget); 1209 pVclWidget->getWidget()->reorderWithinParent(nNewPosition); 1210 } 1211 virtual void sort_native_button_order() override 1212 { 1213 ::sort_native_button_order(*m_xBox); 1214 } 1215 }; 1216 1217 void CollectChildren(const vcl::Window& rCurrent, const basegfx::B2IPoint& rTopLeft, 1218 weld::ScreenShotCollection& rControlDataCollection) 1219 { 1220 if (!rCurrent.IsVisible()) 1221 return; 1222 1223 const Point aCurrentPos(rCurrent.GetPosPixel()); 1224 const Size aCurrentSize(rCurrent.GetSizePixel()); 1225 const basegfx::B2IPoint aCurrentTopLeft(rTopLeft.getX() + aCurrentPos.X(), 1226 rTopLeft.getY() + aCurrentPos.Y()); 1227 const basegfx::B2IRange aCurrentRange( 1228 aCurrentTopLeft, 1229 aCurrentTopLeft + basegfx::B2IPoint(aCurrentSize.Width(), aCurrentSize.Height())); 1230 1231 if (!aCurrentRange.isEmpty()) 1232 { 1233 rControlDataCollection.emplace_back(rCurrent.GetHelpId(), aCurrentRange); 1234 } 1235 1236 for (sal_uInt16 a(0); a < rCurrent.GetChildCount(); a++) 1237 { 1238 vcl::Window* pChild = rCurrent.GetChild(a); 1239 if (nullptr != pChild) 1240 { 1241 CollectChildren(*pChild, aCurrentTopLeft, rControlDataCollection); 1242 } 1243 } 1244 } 1245 1246 } 1247 1248 void SalInstanceWindow::override_child_help(vcl::Window* pParent) 1249 { 1250 for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild; 1251 pChild = pChild->GetWindow(GetWindowType::Next)) 1252 override_child_help(pChild); 1253 pParent->SetHelpHdl(LINK(this, SalInstanceWindow, HelpHdl)); 1254 } 1255 1256 void SalInstanceWindow::clear_child_help(vcl::Window* pParent) 1257 { 1258 for (vcl::Window* pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild; 1259 pChild = pChild->GetWindow(GetWindowType::Next)) 1260 clear_child_help(pChild); 1261 pParent->SetHelpHdl(Link<vcl::Window&, bool>()); 1262 } 1263 1264 SalInstanceWindow::SalInstanceWindow(vcl::Window* pWindow, SalInstanceBuilder* pBuilder, 1265 bool bTakeOwnership) 1266 : SalInstanceContainer(pWindow, pBuilder, bTakeOwnership) 1267 , m_xWindow(pWindow) 1268 { 1269 override_child_help(m_xWindow); 1270 } 1271 1272 void SalInstanceWindow::set_title(const OUString& rTitle) { m_xWindow->SetText(rTitle); } 1273 1274 OUString SalInstanceWindow::get_title() const { return m_xWindow->GetText(); } 1275 1276 void SalInstanceWindow::set_busy_cursor(bool bBusy) 1277 { 1278 if (bBusy) 1279 m_xWindow->EnterWait(); 1280 else 1281 m_xWindow->LeaveWait(); 1282 } 1283 1284 css::uno::Reference<css::awt::XWindow> SalInstanceWindow::GetXWindow() 1285 { 1286 css::uno::Reference<css::awt::XWindow> xWindow(m_xWindow->GetComponentInterface(), 1287 css::uno::UNO_QUERY); 1288 return xWindow; 1289 } 1290 1291 void SalInstanceWindow::resize_to_request() 1292 { 1293 if (SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get())) 1294 { 1295 pSysWin->setOptimalLayoutSize(); 1296 return; 1297 } 1298 if (DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(m_xWindow.get())) 1299 { 1300 pDockWin->setOptimalLayoutSize(); 1301 return; 1302 } 1303 assert(false && "must be system or docking window"); 1304 } 1305 1306 void SalInstanceWindow::set_modal(bool bModal) { m_xWindow->ImplGetFrame()->SetModal(bModal); } 1307 1308 bool SalInstanceWindow::get_modal() const { return m_xWindow->ImplGetFrame()->GetModal(); } 1309 1310 void SalInstanceWindow::window_move(int x, int y) { m_xWindow->SetPosPixel(Point(x, y)); } 1311 1312 Size SalInstanceWindow::get_size() const { return m_xWindow->GetSizePixel(); } 1313 1314 Point SalInstanceWindow::get_position() const { return m_xWindow->GetPosPixel(); } 1315 1316 tools::Rectangle SalInstanceWindow::get_monitor_workarea() const 1317 { 1318 return m_xWindow->GetDesktopRectPixel(); 1319 } 1320 1321 void SalInstanceWindow::set_centered_on_parent(bool /*bTrackGeometryRequests*/) 1322 { 1323 if (vcl::Window* pParent = m_xWidget->GetParent()) 1324 { 1325 Size aParentGeometry(pParent->GetSizePixel()); 1326 Size aGeometry(m_xWidget->get_preferred_size()); 1327 auto nX = (aParentGeometry.Width() - aGeometry.Width()) / 2; 1328 auto nY = (aParentGeometry.Height() - aGeometry.Height()) / 2; 1329 m_xWidget->SetPosPixel(Point(nX, nY)); 1330 } 1331 } 1332 1333 bool SalInstanceWindow::get_resizable() const { return m_xWindow->GetStyle() & WB_SIZEABLE; } 1334 1335 bool SalInstanceWindow::has_toplevel_focus() const { return m_xWindow->HasChildPathFocus(); } 1336 1337 void SalInstanceWindow::present() 1338 { 1339 m_xWindow->ToTop(ToTopFlags::RestoreWhenMin | ToTopFlags::ForegroundTask); 1340 } 1341 1342 void SalInstanceWindow::set_window_state(const OString& rStr) 1343 { 1344 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get()); 1345 assert(pSysWin); 1346 pSysWin->SetWindowState(rStr); 1347 } 1348 1349 OString SalInstanceWindow::get_window_state(WindowStateMask nMask) const 1350 { 1351 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get()); 1352 assert(pSysWin); 1353 return pSysWin->GetWindowState(nMask); 1354 } 1355 1356 SystemEnvData SalInstanceWindow::get_system_data() const { return *m_xWindow->GetSystemData(); } 1357 1358 void SalInstanceWindow::connect_toplevel_focus_changed(const Link<weld::Widget&, void>& rLink) 1359 { 1360 ensure_event_listener(); 1361 weld::Window::connect_toplevel_focus_changed(rLink); 1362 } 1363 1364 void SalInstanceWindow::HandleEventListener(VclWindowEvent& rEvent) 1365 { 1366 if (rEvent.GetId() == VclEventId::WindowActivate 1367 || rEvent.GetId() == VclEventId::WindowDeactivate) 1368 { 1369 signal_toplevel_focus_changed(); 1370 return; 1371 } 1372 SalInstanceContainer::HandleEventListener(rEvent); 1373 } 1374 1375 VclPtr<VirtualDevice> SalInstanceWindow::screenshot() 1376 { 1377 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(m_xWindow.get()); 1378 assert(pSysWin); 1379 return pSysWin->createScreenshot(); 1380 } 1381 1382 weld::ScreenShotCollection SalInstanceWindow::collect_screenshot_data() 1383 { 1384 weld::ScreenShotCollection aRet; 1385 1386 // collect all children. Choose start pos to be negative 1387 // of target dialog's position to get all positions relative to (0,0) 1388 const Point aParentPos(m_xWindow->GetPosPixel()); 1389 const basegfx::B2IPoint aTopLeft(-aParentPos.X(), -aParentPos.Y()); 1390 CollectChildren(*m_xWindow, aTopLeft, aRet); 1391 1392 return aRet; 1393 } 1394 1395 SalInstanceWindow::~SalInstanceWindow() { clear_child_help(m_xWindow); } 1396 1397 IMPL_LINK_NOARG(SalInstanceWindow, HelpHdl, vcl::Window&, bool) 1398 { 1399 help(); 1400 return false; 1401 } 1402 1403 typedef std::set<VclPtr<vcl::Window>> winset; 1404 1405 namespace 1406 { 1407 void hideUnless(const vcl::Window* pTop, const winset& rVisibleWidgets, 1408 std::vector<VclPtr<vcl::Window>>& rWasVisibleWidgets) 1409 { 1410 for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild; 1411 pChild = pChild->GetWindow(GetWindowType::Next)) 1412 { 1413 if (!pChild->IsVisible()) 1414 continue; 1415 if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end()) 1416 { 1417 rWasVisibleWidgets.emplace_back(pChild); 1418 pChild->Hide(); 1419 } 1420 else if (isContainerWindow(pChild)) 1421 { 1422 hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets); 1423 } 1424 } 1425 } 1426 } 1427 1428 SalInstanceDialog::SalInstanceDialog(::Dialog* pDialog, SalInstanceBuilder* pBuilder, 1429 bool bTakeOwnership) 1430 : SalInstanceWindow(pDialog, pBuilder, bTakeOwnership) 1431 , m_xDialog(pDialog) 1432 , m_nOldEditWidthReq(0) 1433 , m_nOldBorderWidth(0) 1434 { 1435 const bool bScreenshotMode(officecfg::Office::Common::Misc::ScreenshotMode::get()); 1436 if (bScreenshotMode) 1437 { 1438 m_xDialog->SetPopupMenuHdl(LINK(this, SalInstanceDialog, PopupScreenShotMenuHdl)); 1439 } 1440 } 1441 1442 bool SalInstanceDialog::runAsync(std::shared_ptr<weld::DialogController> aOwner, 1443 const std::function<void(sal_Int32)>& rEndDialogFn) 1444 { 1445 VclAbstractDialog::AsyncContext aCtx; 1446 aCtx.mxOwnerDialogController = aOwner; 1447 aCtx.maEndDialogFn = rEndDialogFn; 1448 VclButtonBox* pActionArea = m_xDialog->get_action_area(); 1449 if (pActionArea) 1450 sort_native_button_order(*pActionArea); 1451 return m_xDialog->StartExecuteAsync(aCtx); 1452 } 1453 1454 bool SalInstanceDialog::runAsync(std::shared_ptr<Dialog> const& rxSelf, 1455 const std::function<void(sal_Int32)>& rEndDialogFn) 1456 { 1457 assert(rxSelf.get() == this); 1458 VclAbstractDialog::AsyncContext aCtx; 1459 // In order to store a shared_ptr to ourself, we have to have been constructed by make_shared, 1460 // which is that rxSelf enforces. 1461 aCtx.mxOwnerSelf = rxSelf; 1462 aCtx.maEndDialogFn = rEndDialogFn; 1463 VclButtonBox* pActionArea = m_xDialog->get_action_area(); 1464 if (pActionArea) 1465 sort_native_button_order(*pActionArea); 1466 return m_xDialog->StartExecuteAsync(aCtx); 1467 } 1468 1469 void SalInstanceDialog::collapse(weld::Widget* pEdit, weld::Widget* pButton) 1470 { 1471 SalInstanceWidget* pVclEdit = dynamic_cast<SalInstanceWidget*>(pEdit); 1472 assert(pVclEdit); 1473 SalInstanceWidget* pVclButton = dynamic_cast<SalInstanceWidget*>(pButton); 1474 1475 vcl::Window* pRefEdit = pVclEdit->getWidget(); 1476 vcl::Window* pRefBtn = pVclButton ? pVclButton->getWidget() : nullptr; 1477 1478 auto nOldEditWidth = pRefEdit->GetSizePixel().Width(); 1479 m_nOldEditWidthReq = pRefEdit->get_width_request(); 1480 1481 //We want just pRefBtn and pRefEdit to be shown 1482 //mark widgets we want to be visible, starting with pRefEdit 1483 //and all its direct parents. 1484 winset aVisibleWidgets; 1485 vcl::Window* pContentArea = m_xDialog->get_content_area(); 1486 for (vcl::Window* pCandidate = pRefEdit; 1487 pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible()); 1488 pCandidate = pCandidate->GetWindow(GetWindowType::RealParent)) 1489 { 1490 aVisibleWidgets.insert(pCandidate); 1491 } 1492 //same again with pRefBtn, except stop if there's a 1493 //shared parent in the existing widgets 1494 for (vcl::Window* pCandidate = pRefBtn; 1495 pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible()); 1496 pCandidate = pCandidate->GetWindow(GetWindowType::RealParent)) 1497 { 1498 if (aVisibleWidgets.insert(pCandidate).second) 1499 break; 1500 } 1501 1502 //hide everything except the aVisibleWidgets 1503 hideUnless(pContentArea, aVisibleWidgets, m_aHiddenWidgets); 1504 1505 // the insert function case has an initially hidden edit widget, so it has 1506 // not start size, so take larger of actual size and size request 1507 pRefEdit->set_width_request(std::max(nOldEditWidth, m_nOldEditWidthReq)); 1508 m_nOldBorderWidth = m_xDialog->get_border_width(); 1509 m_xDialog->set_border_width(0); 1510 if (vcl::Window* pActionArea = m_xDialog->get_action_area()) 1511 pActionArea->Hide(); 1512 m_xDialog->setOptimalLayoutSize(); 1513 m_xRefEdit = pRefEdit; 1514 } 1515 1516 void SalInstanceDialog::undo_collapse() 1517 { 1518 // All others: Show(); 1519 for (VclPtr<vcl::Window> const& pWindow : m_aHiddenWidgets) 1520 { 1521 pWindow->Show(); 1522 } 1523 m_aHiddenWidgets.clear(); 1524 1525 m_xRefEdit->set_width_request(m_nOldEditWidthReq); 1526 m_xRefEdit.clear(); 1527 m_xDialog->set_border_width(m_nOldBorderWidth); 1528 if (vcl::Window* pActionArea = m_xDialog->get_action_area()) 1529 pActionArea->Show(); 1530 m_xDialog->setOptimalLayoutSize(); 1531 } 1532 1533 void SalInstanceDialog::SetInstallLOKNotifierHdl( 1534 const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink) 1535 { 1536 m_xDialog->SetInstallLOKNotifierHdl(rLink); 1537 } 1538 1539 int SalInstanceDialog::run() 1540 { 1541 VclButtonBox* pActionArea = m_xDialog->get_action_area(); 1542 if (pActionArea) 1543 sort_native_button_order(*pActionArea); 1544 return m_xDialog->Execute(); 1545 } 1546 1547 void SalInstanceDialog::response(int nResponse) { m_xDialog->EndDialog(nResponse); } 1548 1549 void SalInstanceDialog::add_button(const OUString& rText, int nResponse, const OString& rHelpId) 1550 { 1551 VclButtonBox* pBox = m_xDialog->get_action_area(); 1552 VclPtr<PushButton> xButton( 1553 VclPtr<PushButton>::Create(pBox, WB_CLIPCHILDREN | WB_CENTER | WB_VCENTER)); 1554 xButton->SetText(rText); 1555 xButton->SetHelpId(rHelpId); 1556 1557 switch (nResponse) 1558 { 1559 case RET_OK: 1560 xButton->set_id("ok"); 1561 break; 1562 case RET_CLOSE: 1563 xButton->set_id("close"); 1564 break; 1565 case RET_CANCEL: 1566 xButton->set_id("cancel"); 1567 break; 1568 case RET_YES: 1569 xButton->set_id("yes"); 1570 break; 1571 case RET_NO: 1572 xButton->set_id("no"); 1573 break; 1574 } 1575 1576 xButton->Show(); 1577 m_xDialog->add_button(xButton, nResponse, true); 1578 } 1579 1580 void SalInstanceDialog::set_modal(bool bModal) 1581 { 1582 if (get_modal() == bModal) 1583 return; 1584 m_xDialog->SetModalInputMode(bModal); 1585 } 1586 1587 bool SalInstanceDialog::get_modal() const { return m_xDialog->IsModalInputMode(); } 1588 1589 void SalInstanceDialog::set_default_response(int nResponse) 1590 { 1591 m_xDialog->set_default_response(nResponse); 1592 } 1593 1594 weld::Container* SalInstanceDialog::weld_content_area() 1595 { 1596 return new SalInstanceContainer(m_xDialog->get_content_area(), m_pBuilder, false); 1597 } 1598 1599 IMPL_LINK(SalInstanceDialog, PopupScreenShotMenuHdl, const CommandEvent&, rCEvt, bool) 1600 { 1601 if (CommandEventId::ContextMenu == rCEvt.GetCommand()) 1602 { 1603 const Point aMenuPos(rCEvt.GetMousePosPixel()); 1604 ScopedVclPtrInstance<PopupMenu> aMenu; 1605 sal_uInt16 nLocalID(1); 1606 1607 aMenu->InsertItem(nLocalID, VclResId(SV_BUTTONTEXT_SCREENSHOT)); 1608 aMenu->SetHelpText(nLocalID, VclResId(SV_HELPTEXT_SCREENSHOT)); 1609 aMenu->SetHelpId(nLocalID, "InteractiveScreenshotMode"); 1610 aMenu->EnableItem(nLocalID); 1611 1612 const sal_uInt16 nId(aMenu->Execute(m_xDialog, aMenuPos)); 1613 1614 // 0 == no selection (so not usable as ID) 1615 if (0 != nId) 1616 { 1617 // open screenshot annotation dialog 1618 VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create(); 1619 VclPtr<AbstractScreenshotAnnotationDlg> pTmp 1620 = pFact->CreateScreenshotAnnotationDlg(*this); 1621 ScopedVclPtr<AbstractScreenshotAnnotationDlg> pDialog(pTmp); 1622 1623 if (pDialog) 1624 { 1625 // currently just execute the dialog, no need to do 1626 // different things for ok/cancel. This may change later, 1627 // for that case use 'if (pDlg->Execute() == RET_OK)' 1628 pDialog->Execute(); 1629 } 1630 } 1631 1632 // consume event when: 1633 // - CommandEventId::ContextMenu 1634 // - bScreenshotMode 1635 return true; 1636 } 1637 1638 return false; 1639 } 1640 1641 SalInstanceMessageDialog::SalInstanceMessageDialog(::MessageDialog* pDialog, SalInstanceBuilder* pBuilder, 1642 bool bTakeOwnership) 1643 : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership) 1644 , m_xMessageDialog(pDialog) 1645 { 1646 } 1647 1648 void SalInstanceMessageDialog::set_primary_text(const OUString& rText) 1649 { 1650 m_xMessageDialog->set_primary_text(rText); 1651 } 1652 1653 OUString SalInstanceMessageDialog::get_primary_text() const 1654 { 1655 return m_xMessageDialog->get_primary_text(); 1656 } 1657 1658 void SalInstanceMessageDialog::set_secondary_text(const OUString& rText) 1659 { 1660 m_xMessageDialog->set_secondary_text(rText); 1661 } 1662 1663 OUString SalInstanceMessageDialog::get_secondary_text() const 1664 { 1665 return m_xMessageDialog->get_secondary_text(); 1666 } 1667 1668 weld::Container* SalInstanceMessageDialog::weld_message_area() 1669 { 1670 return new SalInstanceContainer(m_xMessageDialog->get_message_area(), m_pBuilder, false); 1671 } 1672 1673 namespace 1674 { 1675 1676 class SalInstanceAssistant : public SalInstanceDialog, public virtual weld::Assistant 1677 { 1678 private: 1679 VclPtr<vcl::RoadmapWizard> m_xWizard; 1680 std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages; 1681 std::vector<VclPtr<TabPage>> m_aAddedPages; 1682 std::vector<int> m_aIds; 1683 std::vector<VclPtr<VclGrid>> m_aAddedGrids; 1684 Idle m_aUpdateRoadmapIdle; 1685 1686 int find_page(const OString& rIdent) const 1687 { 1688 for (size_t i = 0; i < m_aAddedPages.size(); ++i) 1689 { 1690 if (m_aAddedPages[i]->get_id().toUtf8() == rIdent) 1691 return i; 1692 } 1693 return -1; 1694 } 1695 1696 int find_id(int nId) const 1697 { 1698 for (size_t i = 0; i < m_aIds.size(); ++i) 1699 { 1700 if (nId == m_aIds[i]) 1701 return i; 1702 } 1703 return -1; 1704 } 1705 1706 DECL_LINK(OnRoadmapItemSelected, LinkParamNone*, void); 1707 DECL_LINK(UpdateRoadmap_Hdl, Timer*, void); 1708 1709 public: 1710 SalInstanceAssistant(vcl::RoadmapWizard* pDialog, SalInstanceBuilder* pBuilder, 1711 bool bTakeOwnership) 1712 : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership) 1713 , m_xWizard(pDialog) 1714 { 1715 m_xWizard->SetItemSelectHdl(LINK(this, SalInstanceAssistant, OnRoadmapItemSelected)); 1716 1717 m_aUpdateRoadmapIdle.SetInvokeHandler(LINK(this, SalInstanceAssistant, UpdateRoadmap_Hdl)); 1718 m_aUpdateRoadmapIdle.SetPriority(TaskPriority::HIGHEST); 1719 } 1720 1721 virtual int get_current_page() const override { return find_id(m_xWizard->GetCurLevel()); } 1722 1723 virtual int get_n_pages() const override { return m_aAddedPages.size(); } 1724 1725 virtual OString get_page_ident(int nPage) const override 1726 { 1727 return m_aAddedPages[nPage]->get_id().toUtf8(); 1728 } 1729 1730 virtual OString get_current_page_ident() const override 1731 { 1732 return get_page_ident(get_current_page()); 1733 } 1734 1735 virtual void set_current_page(int nPage) override 1736 { 1737 disable_notify_events(); 1738 1739 // take the first shown page as the size for all pages 1740 if (m_xWizard->GetPageSizePixel().Width() == 0) 1741 { 1742 Size aFinalSize; 1743 for (int i = 0, nPages = get_n_pages(); i < nPages; ++i) 1744 { 1745 TabPage* pPage = m_xWizard->GetPage(m_aIds[i]); 1746 assert(pPage); 1747 Size aPageSize(pPage->get_preferred_size()); 1748 if (aPageSize.Width() > aFinalSize.Width()) 1749 aFinalSize.setWidth(aPageSize.Width()); 1750 if (aPageSize.Height() > aFinalSize.Height()) 1751 aFinalSize.setHeight(aPageSize.Height()); 1752 } 1753 m_xWizard->SetPageSizePixel(aFinalSize); 1754 } 1755 1756 (void)m_xWizard->ShowPage(m_aIds[nPage]); 1757 enable_notify_events(); 1758 } 1759 1760 virtual void set_current_page(const OString& rIdent) override 1761 { 1762 int nIndex = find_page(rIdent); 1763 if (nIndex == -1) 1764 return; 1765 set_current_page(nIndex); 1766 } 1767 1768 virtual void set_page_index(const OString& rIdent, int nNewIndex) override 1769 { 1770 int nOldIndex = find_page(rIdent); 1771 1772 if (nOldIndex == -1) 1773 return; 1774 1775 if (nOldIndex == nNewIndex) 1776 return; 1777 1778 disable_notify_events(); 1779 1780 auto entry = std::move(m_aAddedPages[nOldIndex]); 1781 m_aAddedPages.erase(m_aAddedPages.begin() + nOldIndex); 1782 m_aAddedPages.insert(m_aAddedPages.begin() + nNewIndex, std::move(entry)); 1783 1784 int nId = m_aIds[nOldIndex]; 1785 m_aIds.erase(m_aIds.begin() + nOldIndex); 1786 m_aIds.insert(m_aIds.begin() + nNewIndex, nId); 1787 1788 m_aUpdateRoadmapIdle.Start(); 1789 1790 enable_notify_events(); 1791 } 1792 1793 virtual weld::Container* append_page(const OString& rIdent) override 1794 { 1795 VclPtrInstance<TabPage> xPage(m_xWizard); 1796 VclPtrInstance<VclGrid> xGrid(xPage); 1797 xPage->set_id(OUString::fromUtf8(rIdent)); 1798 xPage->Show(); 1799 xGrid->set_hexpand(true); 1800 xGrid->set_vexpand(true); 1801 xGrid->Show(); 1802 m_xWizard->AddPage(xPage); 1803 m_aIds.push_back(m_aAddedPages.size()); 1804 m_xWizard->SetPage(m_aIds.back(), xPage); 1805 m_aAddedPages.push_back(xPage); 1806 m_aAddedGrids.push_back(xGrid); 1807 1808 m_aUpdateRoadmapIdle.Start(); 1809 1810 m_aPages.emplace_back(new SalInstanceContainer(xGrid, m_pBuilder, false)); 1811 return m_aPages.back().get(); 1812 } 1813 1814 virtual OUString get_page_title(const OString& rIdent) const override 1815 { 1816 int nIndex = find_page(rIdent); 1817 if (nIndex == -1) 1818 return OUString(); 1819 return m_aAddedPages[nIndex]->GetText(); 1820 } 1821 1822 virtual void set_page_title(const OString& rIdent, const OUString& rTitle) override 1823 { 1824 int nIndex = find_page(rIdent); 1825 if (nIndex == -1) 1826 return; 1827 if (m_aAddedPages[nIndex]->GetText() != rTitle) 1828 { 1829 disable_notify_events(); 1830 m_aAddedPages[nIndex]->SetText(rTitle); 1831 m_aUpdateRoadmapIdle.Start(); 1832 enable_notify_events(); 1833 } 1834 } 1835 1836 virtual void set_page_sensitive(const OString& rIdent, bool bSensitive) override 1837 { 1838 int nIndex = find_page(rIdent); 1839 if (nIndex == -1) 1840 return; 1841 if (m_aAddedPages[nIndex]->IsEnabled() != bSensitive) 1842 { 1843 disable_notify_events(); 1844 m_aAddedPages[nIndex]->Enable(bSensitive); 1845 m_aUpdateRoadmapIdle.Start(); 1846 enable_notify_events(); 1847 } 1848 } 1849 1850 virtual void set_page_side_help_id(const OString& rHelpId) override 1851 { 1852 m_xWizard->SetRoadmapHelpId(rHelpId); 1853 } 1854 1855 weld::Button* weld_widget_for_response(int nResponse) override; 1856 1857 virtual ~SalInstanceAssistant() override 1858 { 1859 for (auto& rGrid : m_aAddedGrids) 1860 rGrid.disposeAndClear(); 1861 for (auto& rPage : m_aAddedPages) 1862 rPage.disposeAndClear(); 1863 } 1864 }; 1865 1866 } 1867 1868 IMPL_LINK_NOARG(SalInstanceAssistant, OnRoadmapItemSelected, LinkParamNone*, void) 1869 { 1870 if (notify_events_disabled()) 1871 return; 1872 auto nCurItemId = m_xWizard->GetCurrentRoadmapItemID(); 1873 int nPageIndex(find_id(nCurItemId)); 1874 if (!signal_jump_page(get_page_ident(nPageIndex)) && nCurItemId != m_xWizard->GetCurLevel()) 1875 m_xWizard->SelectRoadmapItemByID(m_xWizard->GetCurLevel()); 1876 } 1877 1878 IMPL_LINK_NOARG(SalInstanceAssistant, UpdateRoadmap_Hdl, Timer*, void) 1879 { 1880 disable_notify_events(); 1881 1882 m_xWizard->DeleteRoadmapItems(); 1883 1884 int nPos = 0; 1885 for (size_t i = 0; i < m_aAddedPages.size(); ++i) 1886 { 1887 const OUString& rLabel = m_aAddedPages[i]->GetText(); 1888 bool bSensitive = m_aAddedPages[i]->IsEnabled(); 1889 if (rLabel.isEmpty()) 1890 continue; 1891 m_xWizard->InsertRoadmapItem(nPos++, rLabel, m_aIds[i], bSensitive); 1892 } 1893 1894 m_xWizard->SelectRoadmapItemByID(m_aIds[get_current_page()]); 1895 1896 m_xWizard->ShowRoadmap(nPos != 0); 1897 1898 enable_notify_events(); 1899 } 1900 1901 namespace 1902 { 1903 class SalInstanceFrame : public SalInstanceContainer, public virtual weld::Frame 1904 { 1905 private: 1906 VclPtr<VclFrame> m_xFrame; 1907 1908 public: 1909 SalInstanceFrame(VclFrame* pFrame, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 1910 : SalInstanceContainer(pFrame, pBuilder, bTakeOwnership) 1911 , m_xFrame(pFrame) 1912 { 1913 } 1914 1915 virtual void set_label(const OUString& rText) override { m_xFrame->set_label(rText); } 1916 1917 virtual OUString get_label() const override { return m_xFrame->get_label(); } 1918 1919 virtual std::unique_ptr<weld::Label> weld_label_widget() const override; 1920 }; 1921 1922 class SalInstancePaned : public SalInstanceContainer, public virtual weld::Paned 1923 { 1924 private: 1925 VclPtr<VclPaned> m_xPaned; 1926 1927 public: 1928 SalInstancePaned(VclPaned* pPaned, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 1929 : SalInstanceContainer(pPaned, pBuilder, bTakeOwnership) 1930 , m_xPaned(pPaned) 1931 { 1932 } 1933 1934 virtual void set_position(int nPos) override 1935 { 1936 m_xPaned->set_position(nPos); 1937 } 1938 1939 virtual int get_position() const override 1940 { 1941 return m_xPaned->get_position(); 1942 } 1943 }; 1944 1945 class SalInstanceScrolledWindow : public SalInstanceContainer, public virtual weld::ScrolledWindow 1946 { 1947 private: 1948 VclPtr<VclScrolledWindow> m_xScrolledWindow; 1949 Link<ScrollBar*, void> m_aOrigVScrollHdl; 1950 Link<ScrollBar*, void> m_aOrigHScrollHdl; 1951 bool m_bUserManagedScrolling; 1952 1953 DECL_LINK(VscrollHdl, ScrollBar*, void); 1954 DECL_LINK(HscrollHdl, ScrollBar*, void); 1955 1956 public: 1957 SalInstanceScrolledWindow(VclScrolledWindow* pScrolledWindow, SalInstanceBuilder* pBuilder, 1958 bool bTakeOwnership) 1959 : SalInstanceContainer(pScrolledWindow, pBuilder, bTakeOwnership) 1960 , m_xScrolledWindow(pScrolledWindow) 1961 , m_bUserManagedScrolling(false) 1962 { 1963 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 1964 m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl(); 1965 rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, VscrollHdl)); 1966 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 1967 m_aOrigHScrollHdl = rHorzScrollBar.GetScrollHdl(); 1968 rHorzScrollBar.SetScrollHdl(LINK(this, SalInstanceScrolledWindow, HscrollHdl)); 1969 } 1970 1971 virtual void hadjustment_configure(int value, int lower, int upper, int step_increment, 1972 int page_increment, int page_size) override 1973 { 1974 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 1975 rHorzScrollBar.SetRangeMin(lower); 1976 rHorzScrollBar.SetRangeMax(upper); 1977 rHorzScrollBar.SetLineSize(step_increment); 1978 rHorzScrollBar.SetPageSize(page_increment); 1979 rHorzScrollBar.SetThumbPos(value); 1980 rHorzScrollBar.SetVisibleSize(page_size); 1981 } 1982 1983 virtual int hadjustment_get_value() const override 1984 { 1985 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 1986 return rHorzScrollBar.GetThumbPos(); 1987 } 1988 1989 virtual void hadjustment_set_value(int value) override 1990 { 1991 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 1992 rHorzScrollBar.SetThumbPos(value); 1993 if (!m_bUserManagedScrolling) 1994 m_aOrigHScrollHdl.Call(&rHorzScrollBar); 1995 } 1996 1997 virtual int hadjustment_get_upper() const override 1998 { 1999 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 2000 return rHorzScrollBar.GetRangeMax(); 2001 } 2002 2003 virtual void hadjustment_set_upper(int upper) override 2004 { 2005 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 2006 rHorzScrollBar.SetRangeMax(upper); 2007 } 2008 2009 virtual int hadjustment_get_page_size() const override 2010 { 2011 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 2012 return rHorzScrollBar.GetVisibleSize(); 2013 } 2014 2015 virtual void hadjustment_set_page_size(int size) override 2016 { 2017 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 2018 return rHorzScrollBar.SetVisibleSize(size); 2019 } 2020 2021 virtual void hadjustment_set_page_increment(int size) override 2022 { 2023 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 2024 return rHorzScrollBar.SetPageSize(size); 2025 } 2026 2027 virtual void hadjustment_set_step_increment(int size) override 2028 { 2029 ScrollBar& rHorzScrollBar = m_xScrolledWindow->getHorzScrollBar(); 2030 return rHorzScrollBar.SetLineSize(size); 2031 } 2032 2033 virtual void set_hpolicy(VclPolicyType eHPolicy) override 2034 { 2035 WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOHSCROLL | WB_HSCROLL); 2036 if (eHPolicy == VclPolicyType::ALWAYS) 2037 nWinBits |= WB_HSCROLL; 2038 else if (eHPolicy == VclPolicyType::AUTOMATIC) 2039 nWinBits |= WB_AUTOHSCROLL; 2040 m_xScrolledWindow->SetStyle(nWinBits); 2041 m_xScrolledWindow->queue_resize(); 2042 } 2043 2044 virtual VclPolicyType get_hpolicy() const override 2045 { 2046 WinBits nWinBits = m_xScrolledWindow->GetStyle(); 2047 if (nWinBits & WB_AUTOHSCROLL) 2048 return VclPolicyType::AUTOMATIC; 2049 else if (nWinBits & WB_HSCROLL) 2050 return VclPolicyType::ALWAYS; 2051 return VclPolicyType::NEVER; 2052 } 2053 2054 virtual int get_hscroll_height() const override 2055 { 2056 return m_xScrolledWindow->getHorzScrollBar().get_preferred_size().Height(); 2057 } 2058 2059 virtual void vadjustment_configure(int value, int lower, int upper, int step_increment, 2060 int page_increment, int page_size) override 2061 { 2062 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2063 rVertScrollBar.SetRangeMin(lower); 2064 rVertScrollBar.SetRangeMax(upper); 2065 rVertScrollBar.SetLineSize(step_increment); 2066 rVertScrollBar.SetPageSize(page_increment); 2067 rVertScrollBar.SetThumbPos(value); 2068 rVertScrollBar.SetVisibleSize(page_size); 2069 } 2070 2071 virtual int vadjustment_get_value() const override 2072 { 2073 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2074 return rVertScrollBar.GetThumbPos(); 2075 } 2076 2077 virtual void vadjustment_set_value(int value) override 2078 { 2079 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2080 rVertScrollBar.SetThumbPos(value); 2081 if (!m_bUserManagedScrolling) 2082 m_aOrigVScrollHdl.Call(&rVertScrollBar); 2083 } 2084 2085 virtual int vadjustment_get_upper() const override 2086 { 2087 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2088 return rVertScrollBar.GetRangeMax(); 2089 } 2090 2091 virtual void vadjustment_set_upper(int upper) override 2092 { 2093 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2094 rVertScrollBar.SetRangeMax(upper); 2095 } 2096 2097 virtual int vadjustment_get_lower() const override 2098 { 2099 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2100 return rVertScrollBar.GetRangeMin(); 2101 } 2102 2103 virtual void vadjustment_set_lower(int lower) override 2104 { 2105 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2106 rVertScrollBar.SetRangeMin(lower); 2107 } 2108 2109 virtual int vadjustment_get_page_size() const override 2110 { 2111 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2112 return rVertScrollBar.GetVisibleSize(); 2113 } 2114 2115 virtual void vadjustment_set_page_size(int size) override 2116 { 2117 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2118 return rVertScrollBar.SetVisibleSize(size); 2119 } 2120 2121 virtual void vadjustment_set_page_increment(int size) override 2122 { 2123 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2124 return rVertScrollBar.SetPageSize(size); 2125 } 2126 2127 virtual void vadjustment_set_step_increment(int size) override 2128 { 2129 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2130 return rVertScrollBar.SetLineSize(size); 2131 } 2132 2133 virtual void set_vpolicy(VclPolicyType eVPolicy) override 2134 { 2135 WinBits nWinBits = m_xScrolledWindow->GetStyle() & ~(WB_AUTOVSCROLL | WB_VSCROLL); 2136 if (eVPolicy == VclPolicyType::ALWAYS) 2137 nWinBits |= WB_VSCROLL; 2138 else if (eVPolicy == VclPolicyType::AUTOMATIC) 2139 nWinBits |= WB_AUTOVSCROLL; 2140 m_xScrolledWindow->SetStyle(nWinBits); 2141 m_xScrolledWindow->queue_resize(); 2142 } 2143 2144 virtual VclPolicyType get_vpolicy() const override 2145 { 2146 WinBits nWinBits = m_xScrolledWindow->GetStyle(); 2147 if (nWinBits & WB_AUTOVSCROLL) 2148 return VclPolicyType::AUTOMATIC; 2149 else if (nWinBits & WB_VSCROLL) 2150 return VclPolicyType::ALWAYS; 2151 return VclPolicyType::NEVER; 2152 } 2153 2154 virtual int get_vscroll_width() const override 2155 { 2156 return m_xScrolledWindow->getVertScrollBar().get_preferred_size().Width(); 2157 } 2158 2159 virtual void set_user_managed_scrolling() override 2160 { 2161 m_bUserManagedScrolling = true; 2162 m_xScrolledWindow->setUserManagedScrolling(true); 2163 } 2164 2165 virtual ~SalInstanceScrolledWindow() override 2166 { 2167 ScrollBar& rVertScrollBar = m_xScrolledWindow->getVertScrollBar(); 2168 rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl); 2169 } 2170 }; 2171 2172 } 2173 2174 IMPL_LINK(SalInstanceScrolledWindow, VscrollHdl, ScrollBar*, pScrollBar, void) 2175 { 2176 signal_vadjustment_changed(); 2177 if (!m_bUserManagedScrolling) 2178 m_aOrigVScrollHdl.Call(pScrollBar); 2179 } 2180 2181 IMPL_LINK_NOARG(SalInstanceScrolledWindow, HscrollHdl, ScrollBar*, void) 2182 { 2183 signal_hadjustment_changed(); 2184 if (!m_bUserManagedScrolling) 2185 m_aOrigHScrollHdl.Call(&m_xScrolledWindow->getHorzScrollBar()); 2186 } 2187 2188 SalInstanceNotebook::SalInstanceNotebook(TabControl* pNotebook, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2189 : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership) 2190 , m_xNotebook(pNotebook) 2191 { 2192 m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceNotebook, ActivatePageHdl)); 2193 m_xNotebook->SetDeactivatePageHdl(LINK(this, SalInstanceNotebook, DeactivatePageHdl)); 2194 } 2195 2196 int SalInstanceNotebook::get_current_page() const 2197 { 2198 return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId()); 2199 } 2200 2201 OString SalInstanceNotebook::get_page_ident(int nPage) const 2202 { 2203 return m_xNotebook->GetPageName(m_xNotebook->GetPageId(nPage)); 2204 } 2205 2206 OString SalInstanceNotebook::get_current_page_ident() const 2207 { 2208 return m_xNotebook->GetPageName(m_xNotebook->GetCurPageId()); 2209 } 2210 2211 int SalInstanceNotebook::get_page_index(const OString& rIdent) const 2212 { 2213 sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent); 2214 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId); 2215 if (nPageIndex == TAB_PAGE_NOTFOUND) 2216 return -1; 2217 return nPageIndex; 2218 } 2219 2220 weld::Container* SalInstanceNotebook::get_page(const OString& rIdent) const 2221 { 2222 int nPageIndex = get_page_index(rIdent); 2223 if (nPageIndex == -1) 2224 return nullptr; 2225 sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent); 2226 TabPage* pPage = m_xNotebook->GetTabPage(nPageId); 2227 vcl::Window* pChild = pPage->GetChild(0); 2228 if (m_aPages.size() < nPageIndex + 1U) 2229 m_aPages.resize(nPageIndex + 1U); 2230 if (!m_aPages[nPageIndex]) 2231 m_aPages[nPageIndex] = std::make_shared<SalInstanceContainer>(pChild, m_pBuilder, false); 2232 return m_aPages[nPageIndex].get(); 2233 } 2234 2235 void SalInstanceNotebook::set_current_page(int nPage) 2236 { 2237 m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage)); 2238 } 2239 2240 void SalInstanceNotebook::set_current_page(const OString& rIdent) 2241 { 2242 m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(rIdent)); 2243 } 2244 2245 void SalInstanceNotebook::remove_page(const OString& rIdent) 2246 { 2247 sal_uInt16 nPageId = m_xNotebook->GetPageId(rIdent); 2248 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(nPageId); 2249 if (nPageIndex == TAB_PAGE_NOTFOUND) 2250 return; 2251 2252 m_xNotebook->RemovePage(nPageId); 2253 if (nPageIndex < m_aPages.size()) 2254 m_aPages.erase(m_aPages.begin() + nPageIndex); 2255 2256 auto iter = m_aAddedPages.find(rIdent); 2257 if (iter != m_aAddedPages.end()) 2258 { 2259 iter->second.second.disposeAndClear(); 2260 iter->second.first.disposeAndClear(); 2261 m_aAddedPages.erase(iter); 2262 } 2263 } 2264 2265 void SalInstanceNotebook::insert_page(const OString& rIdent, const OUString& rLabel, int nPos) 2266 { 2267 sal_uInt16 nPageCount = m_xNotebook->GetPageCount(); 2268 sal_uInt16 nLastPageId = nPageCount ? m_xNotebook->GetPageId(nPageCount - 1) : 0; 2269 sal_uInt16 nNewPageId = nLastPageId + 1; 2270 while (m_xNotebook->GetPagePos(nNewPageId) != TAB_PAGE_NOTFOUND) 2271 ++nNewPageId; 2272 m_xNotebook->InsertPage(nNewPageId, rLabel, nPos == -1 ? TAB_APPEND : nPos); 2273 VclPtrInstance<TabPage> xPage(m_xNotebook); 2274 VclPtrInstance<VclGrid> xGrid(xPage); 2275 xPage->Show(); 2276 xGrid->set_hexpand(true); 2277 xGrid->set_vexpand(true); 2278 xGrid->Show(); 2279 m_xNotebook->SetTabPage(nNewPageId, xPage); 2280 m_xNotebook->SetPageName(nNewPageId, rIdent); 2281 m_aAddedPages.try_emplace(rIdent, xPage, xGrid); 2282 2283 if (nPos != -1) 2284 { 2285 unsigned int nPageIndex = static_cast<unsigned int>(nPos); 2286 if (nPageIndex < m_aPages.size()) 2287 m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr); 2288 } 2289 } 2290 2291 int SalInstanceNotebook::get_n_pages() const { return m_xNotebook->GetPageCount(); } 2292 2293 OUString SalInstanceNotebook::get_tab_label_text(const OString& rIdent) const 2294 { 2295 return m_xNotebook->GetPageText(m_xNotebook->GetPageId(rIdent)); 2296 } 2297 2298 void SalInstanceNotebook::set_tab_label_text(const OString& rIdent, const OUString& rText) 2299 { 2300 return m_xNotebook->SetPageText(m_xNotebook->GetPageId(rIdent), rText); 2301 } 2302 2303 SalInstanceNotebook::~SalInstanceNotebook() 2304 { 2305 for (auto& rItem : m_aAddedPages) 2306 { 2307 rItem.second.second.disposeAndClear(); 2308 rItem.second.first.disposeAndClear(); 2309 } 2310 m_xNotebook->SetActivatePageHdl(Link<TabControl*, void>()); 2311 m_xNotebook->SetDeactivatePageHdl(Link<TabControl*, bool>()); 2312 } 2313 2314 IMPL_LINK_NOARG(SalInstanceNotebook, DeactivatePageHdl, TabControl*, bool) 2315 { 2316 return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident()); 2317 } 2318 2319 IMPL_LINK_NOARG(SalInstanceNotebook, ActivatePageHdl, TabControl*, void) 2320 { 2321 m_aEnterPageHdl.Call(get_current_page_ident()); 2322 } 2323 2324 namespace 2325 { 2326 class SalInstanceVerticalNotebook : public SalInstanceContainer, public virtual weld::Notebook 2327 { 2328 private: 2329 VclPtr<VerticalTabControl> m_xNotebook; 2330 mutable std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages; 2331 2332 DECL_LINK(DeactivatePageHdl, VerticalTabControl*, bool); 2333 DECL_LINK(ActivatePageHdl, VerticalTabControl*, void); 2334 2335 public: 2336 SalInstanceVerticalNotebook(VerticalTabControl* pNotebook, SalInstanceBuilder* pBuilder, 2337 bool bTakeOwnership) 2338 : SalInstanceContainer(pNotebook, pBuilder, bTakeOwnership) 2339 , m_xNotebook(pNotebook) 2340 { 2341 m_xNotebook->SetActivatePageHdl(LINK(this, SalInstanceVerticalNotebook, ActivatePageHdl)); 2342 m_xNotebook->SetDeactivatePageHdl( 2343 LINK(this, SalInstanceVerticalNotebook, DeactivatePageHdl)); 2344 } 2345 2346 virtual int get_current_page() const override 2347 { 2348 return m_xNotebook->GetPagePos(m_xNotebook->GetCurPageId()); 2349 } 2350 2351 virtual OString get_page_ident(int nPage) const override 2352 { 2353 return m_xNotebook->GetPageId(nPage); 2354 } 2355 2356 virtual OString get_current_page_ident() const override { return m_xNotebook->GetCurPageId(); } 2357 2358 virtual int get_page_index(const OString& rIdent) const override 2359 { 2360 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent); 2361 if (nPageIndex == TAB_PAGE_NOTFOUND) 2362 return -1; 2363 return nPageIndex; 2364 } 2365 2366 virtual weld::Container* get_page(const OString& rIdent) const override 2367 { 2368 int nPageIndex = get_page_index(rIdent); 2369 if (nPageIndex == -1) 2370 return nullptr; 2371 auto pChild = m_xNotebook->GetPage(rIdent); 2372 if (m_aPages.size() < nPageIndex + 1U) 2373 m_aPages.resize(nPageIndex + 1U); 2374 if (!m_aPages[nPageIndex]) 2375 m_aPages[nPageIndex].reset(new SalInstanceContainer(pChild, m_pBuilder, false)); 2376 return m_aPages[nPageIndex].get(); 2377 } 2378 2379 virtual void set_current_page(int nPage) override 2380 { 2381 m_xNotebook->SetCurPageId(m_xNotebook->GetPageId(nPage)); 2382 } 2383 2384 virtual void set_current_page(const OString& rIdent) override 2385 { 2386 m_xNotebook->SetCurPageId(rIdent); 2387 } 2388 2389 virtual void remove_page(const OString& rIdent) override 2390 { 2391 sal_uInt16 nPageIndex = m_xNotebook->GetPagePos(rIdent); 2392 if (nPageIndex == TAB_PAGE_NOTFOUND) 2393 return; 2394 m_xNotebook->RemovePage(rIdent); 2395 if (nPageIndex < m_aPages.size()) 2396 m_aPages.erase(m_aPages.begin() + nPageIndex); 2397 } 2398 2399 virtual void insert_page(const OString& rIdent, const OUString& rLabel, int nPos) override 2400 { 2401 VclPtrInstance<VclGrid> xGrid(m_xNotebook->GetPageParent()); 2402 xGrid->set_hexpand(true); 2403 xGrid->set_vexpand(true); 2404 m_xNotebook->InsertPage(rIdent, rLabel, Image(), "", xGrid, nPos); 2405 2406 if (nPos != -1) 2407 { 2408 unsigned int nPageIndex = static_cast<unsigned int>(nPos); 2409 if (nPageIndex < m_aPages.size()) 2410 m_aPages.insert(m_aPages.begin() + nPageIndex, nullptr); 2411 } 2412 } 2413 2414 virtual int get_n_pages() const override { return m_xNotebook->GetPageCount(); } 2415 2416 virtual void set_tab_label_text(const OString& rIdent, const OUString& rText) override 2417 { 2418 return m_xNotebook->SetPageText(rIdent, rText); 2419 } 2420 2421 virtual OUString get_tab_label_text(const OString& rIdent) const override 2422 { 2423 return m_xNotebook->GetPageText(rIdent); 2424 } 2425 2426 virtual ~SalInstanceVerticalNotebook() override 2427 { 2428 m_xNotebook->SetActivatePageHdl(Link<VerticalTabControl*, void>()); 2429 m_xNotebook->SetDeactivatePageHdl(Link<VerticalTabControl*, bool>()); 2430 } 2431 }; 2432 2433 } 2434 2435 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, DeactivatePageHdl, VerticalTabControl*, bool) 2436 { 2437 return !m_aLeavePageHdl.IsSet() || m_aLeavePageHdl.Call(get_current_page_ident()); 2438 } 2439 2440 IMPL_LINK_NOARG(SalInstanceVerticalNotebook, ActivatePageHdl, VerticalTabControl*, void) 2441 { 2442 m_aEnterPageHdl.Call(get_current_page_ident()); 2443 } 2444 2445 SalInstanceButton::SalInstanceButton(::Button* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2446 : SalInstanceContainer(pButton, pBuilder, bTakeOwnership) 2447 , m_xButton(pButton) 2448 , m_aOldClickHdl(pButton->GetClickHdl()) 2449 { 2450 m_xButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl)); 2451 } 2452 2453 void SalInstanceButton::set_label(const OUString& rText) { m_xButton->SetText(rText); } 2454 2455 void SalInstanceButton::set_image(VirtualDevice* pDevice) 2456 { 2457 m_xButton->SetImageAlign(ImageAlign::Left); 2458 if (pDevice) 2459 m_xButton->SetModeImage(createImage(*pDevice)); 2460 else 2461 m_xButton->SetModeImage(Image()); 2462 } 2463 2464 void SalInstanceButton::set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) 2465 { 2466 m_xButton->SetImageAlign(ImageAlign::Left); 2467 m_xButton->SetModeImage(Image(rImage)); 2468 } 2469 2470 void SalInstanceButton::set_from_icon_name(const OUString& rIconName) 2471 { 2472 m_xButton->SetModeImage(Image(StockImage::Yes, rIconName)); 2473 } 2474 2475 void SalInstanceButton::set_label_line_wrap(bool wrap) 2476 { 2477 WinBits nBits = m_xButton->GetStyle(); 2478 nBits &= ~WB_WORDBREAK; 2479 if (wrap) 2480 nBits |= WB_WORDBREAK; 2481 m_xButton->SetStyle(nBits); 2482 m_xButton->queue_resize(); 2483 } 2484 2485 OUString SalInstanceButton::get_label() const { return m_xButton->GetText(); } 2486 2487 SalInstanceButton::~SalInstanceButton() { m_xButton->SetClickHdl(Link<::Button*, void>()); } 2488 2489 IMPL_LINK(SalInstanceButton, ClickHdl, ::Button*, pButton, void) 2490 { 2491 //if there's no handler set, disengage our intercept and 2492 //run the click again to get default behaviour for cancel/ok 2493 //etc buttons. 2494 if (!m_aClickHdl.IsSet()) 2495 { 2496 pButton->SetClickHdl(m_aOldClickHdl); 2497 pButton->Click(); 2498 pButton->SetClickHdl(LINK(this, SalInstanceButton, ClickHdl)); 2499 return; 2500 } 2501 signal_clicked(); 2502 } 2503 2504 weld::Button* SalInstanceDialog::weld_widget_for_response(int nResponse) 2505 { 2506 PushButton* pButton = dynamic_cast<PushButton*>(m_xDialog->get_widget_for_response(nResponse)); 2507 return pButton ? new SalInstanceButton(pButton, nullptr, false) : nullptr; 2508 } 2509 2510 weld::Button* SalInstanceAssistant::weld_widget_for_response(int nResponse) 2511 { 2512 PushButton* pButton = nullptr; 2513 if (nResponse == RET_YES) 2514 pButton = m_xWizard->m_pNextPage; 2515 else if (nResponse == RET_NO) 2516 pButton = m_xWizard->m_pPrevPage; 2517 else if (nResponse == RET_OK) 2518 pButton = m_xWizard->m_pFinish; 2519 else if (nResponse == RET_CANCEL) 2520 pButton = m_xWizard->m_pCancel; 2521 else if (nResponse == RET_HELP) 2522 pButton = m_xWizard->m_pHelp; 2523 if (pButton) 2524 return new SalInstanceButton(pButton, nullptr, false); 2525 return nullptr; 2526 } 2527 2528 namespace 2529 { 2530 class SalInstanceMenuButton : public SalInstanceButton, public virtual weld::MenuButton 2531 { 2532 private: 2533 VclPtr<::MenuButton> m_xMenuButton; 2534 sal_uInt16 m_nLastId; 2535 2536 DECL_LINK(MenuSelectHdl, ::MenuButton*, void); 2537 DECL_LINK(ActivateHdl, ::MenuButton*, void); 2538 2539 public: 2540 SalInstanceMenuButton(::MenuButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2541 : SalInstanceButton(pButton, pBuilder, bTakeOwnership) 2542 , m_xMenuButton(pButton) 2543 , m_nLastId(0) 2544 { 2545 m_xMenuButton->SetActivateHdl(LINK(this, SalInstanceMenuButton, ActivateHdl)); 2546 m_xMenuButton->SetSelectHdl(LINK(this, SalInstanceMenuButton, MenuSelectHdl)); 2547 if (PopupMenu* pMenu = m_xMenuButton->GetPopupMenu()) 2548 { 2549 pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics); 2550 const auto nCount = pMenu->GetItemCount(); 2551 m_nLastId = nCount ? pMenu->GetItemId(nCount - 1) : 0; 2552 } 2553 } 2554 2555 virtual void set_active(bool active) override 2556 { 2557 if (active == get_active()) 2558 return; 2559 if (active) 2560 m_xMenuButton->ExecuteMenu(); 2561 else 2562 m_xMenuButton->CancelMenu(); 2563 } 2564 2565 virtual bool get_active() const override { return m_xMenuButton->InPopupMode(); } 2566 2567 virtual void set_inconsistent(bool /*inconsistent*/) override 2568 { 2569 //not available 2570 } 2571 2572 virtual bool get_inconsistent() const override { return false; } 2573 2574 virtual void insert_item(int pos, const OUString& rId, const OUString& rStr, 2575 const OUString* pIconName, VirtualDevice* pImageSurface, 2576 TriState eCheckRadioFalse) override 2577 { 2578 m_nLastId = insert_to_menu(m_nLastId, m_xMenuButton->GetPopupMenu(), pos, rId, rStr, 2579 pIconName, pImageSurface, eCheckRadioFalse); 2580 } 2581 2582 virtual void insert_separator(int pos, const OUString& rId) override 2583 { 2584 auto nInsertPos = pos == -1 ? MENU_APPEND : pos; 2585 m_xMenuButton->GetPopupMenu()->InsertSeparator(rId.toUtf8(), nInsertPos); 2586 } 2587 2588 virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) override 2589 { 2590 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2591 pMenu->EnableItem(rIdent, bSensitive); 2592 } 2593 2594 virtual void remove_item(const OString& rId) override 2595 { 2596 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2597 pMenu->RemoveItem(pMenu->GetItemPos(pMenu->GetItemId(rId))); 2598 } 2599 2600 virtual void clear() override 2601 { 2602 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2603 pMenu->Clear(); 2604 } 2605 2606 virtual void set_item_active(const OString& rIdent, bool bActive) override 2607 { 2608 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2609 pMenu->CheckItem(rIdent, bActive); 2610 } 2611 2612 virtual void set_item_label(const OString& rIdent, const OUString& rText) override 2613 { 2614 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2615 pMenu->SetItemText(pMenu->GetItemId(rIdent), rText); 2616 } 2617 2618 virtual OUString get_item_label(const OString& rIdent) const override 2619 { 2620 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2621 return pMenu->GetItemText(pMenu->GetItemId(rIdent)); 2622 } 2623 2624 virtual void set_item_visible(const OString& rIdent, bool bShow) override 2625 { 2626 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2627 pMenu->ShowItem(pMenu->GetItemId(rIdent), bShow); 2628 } 2629 2630 virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) override 2631 { 2632 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2633 pMenu->SetHelpId(pMenu->GetItemId(rIdent), rHelpId); 2634 } 2635 2636 virtual OString get_item_help_id(const OString& rIdent) const override 2637 { 2638 PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); 2639 return pMenu->GetHelpId(pMenu->GetItemId(rIdent)); 2640 } 2641 2642 virtual void set_popover(weld::Widget* pPopover) override 2643 { 2644 SalInstanceWidget* pPopoverWidget = dynamic_cast<SalInstanceWidget*>(pPopover); 2645 m_xMenuButton->SetPopover(pPopoverWidget ? pPopoverWidget->getWidget() : nullptr); 2646 } 2647 2648 virtual ~SalInstanceMenuButton() override 2649 { 2650 m_xMenuButton->SetSelectHdl(Link<::MenuButton*, void>()); 2651 m_xMenuButton->SetActivateHdl(Link<::MenuButton*, void>()); 2652 } 2653 }; 2654 2655 } 2656 2657 IMPL_LINK_NOARG(SalInstanceMenuButton, MenuSelectHdl, ::MenuButton*, void) 2658 { 2659 signal_selected(m_xMenuButton->GetCurItemIdent()); 2660 } 2661 2662 IMPL_LINK_NOARG(SalInstanceMenuButton, ActivateHdl, ::MenuButton*, void) 2663 { 2664 if (notify_events_disabled()) 2665 return; 2666 signal_toggled(); 2667 } 2668 2669 namespace 2670 { 2671 class SalInstanceLinkButton : public SalInstanceContainer, public virtual weld::LinkButton 2672 { 2673 private: 2674 VclPtr<FixedHyperlink> m_xButton; 2675 Link<FixedHyperlink&, void> m_aOrigClickHdl; 2676 2677 DECL_LINK(ClickHdl, FixedHyperlink&, void); 2678 2679 public: 2680 SalInstanceLinkButton(FixedHyperlink* pButton, SalInstanceBuilder* pBuilder, 2681 bool bTakeOwnership) 2682 : SalInstanceContainer(pButton, pBuilder, bTakeOwnership) 2683 , m_xButton(pButton) 2684 { 2685 m_aOrigClickHdl = m_xButton->GetClickHdl(); 2686 m_xButton->SetClickHdl(LINK(this, SalInstanceLinkButton, ClickHdl)); 2687 } 2688 2689 virtual void set_label(const OUString& rText) override { m_xButton->SetText(rText); } 2690 2691 virtual OUString get_label() const override { return m_xButton->GetText(); } 2692 2693 virtual void set_uri(const OUString& rUri) override { m_xButton->SetURL(rUri); } 2694 2695 virtual OUString get_uri() const override { return m_xButton->GetURL(); } 2696 2697 virtual ~SalInstanceLinkButton() override { m_xButton->SetClickHdl(m_aOrigClickHdl); } 2698 }; 2699 2700 } 2701 2702 IMPL_LINK(SalInstanceLinkButton, ClickHdl, FixedHyperlink&, rButton, void) 2703 { 2704 bool bConsumed = signal_activate_link(); 2705 if (!bConsumed) 2706 m_aOrigClickHdl.Call(rButton); 2707 } 2708 2709 namespace 2710 { 2711 class SalInstanceRadioButton : public SalInstanceButton, public virtual weld::RadioButton 2712 { 2713 private: 2714 VclPtr<::RadioButton> m_xRadioButton; 2715 2716 DECL_LINK(ToggleHdl, ::RadioButton&, void); 2717 2718 public: 2719 SalInstanceRadioButton(::RadioButton* pButton, SalInstanceBuilder* pBuilder, 2720 bool bTakeOwnership) 2721 : SalInstanceButton(pButton, pBuilder, bTakeOwnership) 2722 , m_xRadioButton(pButton) 2723 { 2724 m_xRadioButton->SetToggleHdl(LINK(this, SalInstanceRadioButton, ToggleHdl)); 2725 } 2726 2727 virtual void set_active(bool active) override 2728 { 2729 disable_notify_events(); 2730 m_xRadioButton->Check(active); 2731 enable_notify_events(); 2732 } 2733 2734 virtual bool get_active() const override { return m_xRadioButton->IsChecked(); } 2735 2736 virtual void set_image(VirtualDevice* pDevice) override 2737 { 2738 m_xRadioButton->SetImageAlign(ImageAlign::Center); 2739 if (pDevice) 2740 m_xRadioButton->SetModeImage(createImage(*pDevice)); 2741 else 2742 m_xRadioButton->SetModeImage(Image()); 2743 } 2744 2745 virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override 2746 { 2747 m_xRadioButton->SetImageAlign(ImageAlign::Center); 2748 m_xRadioButton->SetModeImage(Image(rImage)); 2749 } 2750 2751 virtual void set_from_icon_name(const OUString& rIconName) override 2752 { 2753 m_xRadioButton->SetModeRadioImage(Image(StockImage::Yes, rIconName)); 2754 } 2755 2756 virtual void set_inconsistent(bool /*inconsistent*/) override 2757 { 2758 //not available 2759 } 2760 2761 virtual bool get_inconsistent() const override { return false; } 2762 2763 virtual ~SalInstanceRadioButton() override 2764 { 2765 m_xRadioButton->SetToggleHdl(Link<::RadioButton&, void>()); 2766 } 2767 }; 2768 2769 } 2770 2771 IMPL_LINK_NOARG(SalInstanceRadioButton, ToggleHdl, ::RadioButton&, void) 2772 { 2773 if (notify_events_disabled()) 2774 return; 2775 signal_toggled(); 2776 } 2777 2778 namespace 2779 { 2780 class SalInstanceToggleButton : public SalInstanceButton, public virtual weld::ToggleButton 2781 { 2782 private: 2783 VclPtr<PushButton> m_xToggleButton; 2784 2785 DECL_LINK(ToggleListener, VclWindowEvent&, void); 2786 2787 public: 2788 SalInstanceToggleButton(PushButton* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2789 : SalInstanceButton(pButton, pBuilder, bTakeOwnership) 2790 , m_xToggleButton(pButton) 2791 { 2792 } 2793 2794 virtual void connect_toggled(const Link<ToggleButton&, void>& rLink) override 2795 { 2796 assert(!m_aToggleHdl.IsSet()); 2797 m_xToggleButton->AddEventListener(LINK(this, SalInstanceToggleButton, ToggleListener)); 2798 weld::ToggleButton::connect_toggled(rLink); 2799 } 2800 2801 virtual void set_active(bool active) override 2802 { 2803 disable_notify_events(); 2804 m_xToggleButton->Check(active); 2805 enable_notify_events(); 2806 } 2807 2808 virtual bool get_active() const override { return m_xToggleButton->IsChecked(); } 2809 2810 virtual void set_inconsistent(bool inconsistent) override 2811 { 2812 disable_notify_events(); 2813 m_xToggleButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE); 2814 enable_notify_events(); 2815 } 2816 2817 virtual bool get_inconsistent() const override 2818 { 2819 return m_xToggleButton->GetState() == TRISTATE_INDET; 2820 } 2821 2822 virtual ~SalInstanceToggleButton() override 2823 { 2824 if (m_aToggleHdl.IsSet()) 2825 m_xToggleButton->RemoveEventListener( 2826 LINK(this, SalInstanceToggleButton, ToggleListener)); 2827 } 2828 }; 2829 2830 } 2831 2832 IMPL_LINK(SalInstanceToggleButton, ToggleListener, VclWindowEvent&, rEvent, void) 2833 { 2834 if (notify_events_disabled()) 2835 return; 2836 if (rEvent.GetId() == VclEventId::PushbuttonToggle) 2837 signal_toggled(); 2838 } 2839 2840 SalInstanceCheckButton::SalInstanceCheckButton(CheckBox* pButton, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2841 : SalInstanceButton(pButton, pBuilder, bTakeOwnership) 2842 , m_xCheckButton(pButton) 2843 { 2844 m_xCheckButton->SetToggleHdl(LINK(this, SalInstanceCheckButton, ToggleHdl)); 2845 } 2846 2847 void SalInstanceCheckButton::set_active(bool active) 2848 { 2849 disable_notify_events(); 2850 m_xCheckButton->EnableTriState(false); 2851 m_xCheckButton->Check(active); 2852 enable_notify_events(); 2853 } 2854 2855 bool SalInstanceCheckButton::get_active() const { return m_xCheckButton->IsChecked(); } 2856 2857 void SalInstanceCheckButton::set_inconsistent(bool inconsistent) 2858 { 2859 disable_notify_events(); 2860 m_xCheckButton->EnableTriState(true); 2861 m_xCheckButton->SetState(inconsistent ? TRISTATE_INDET : TRISTATE_FALSE); 2862 enable_notify_events(); 2863 } 2864 2865 bool SalInstanceCheckButton::get_inconsistent() const 2866 { 2867 return m_xCheckButton->GetState() == TRISTATE_INDET; 2868 } 2869 2870 SalInstanceCheckButton::~SalInstanceCheckButton() 2871 { 2872 m_xCheckButton->SetToggleHdl(Link<CheckBox&, void>()); 2873 } 2874 2875 IMPL_LINK_NOARG(SalInstanceCheckButton, ToggleHdl, CheckBox&, void) 2876 { 2877 if (notify_events_disabled()) 2878 return; 2879 m_xCheckButton->EnableTriState(false); 2880 signal_toggled(); 2881 } 2882 2883 namespace 2884 { 2885 class SalInstanceScale : public SalInstanceWidget, public virtual weld::Scale 2886 { 2887 private: 2888 VclPtr<Slider> m_xScale; 2889 2890 DECL_LINK(SlideHdl, Slider*, void); 2891 2892 public: 2893 SalInstanceScale(Slider* pScale, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2894 : SalInstanceWidget(pScale, pBuilder, bTakeOwnership) 2895 , m_xScale(pScale) 2896 { 2897 m_xScale->SetSlideHdl(LINK(this, SalInstanceScale, SlideHdl)); 2898 } 2899 2900 virtual void set_value(int value) override { m_xScale->SetThumbPos(value); } 2901 2902 virtual void set_range(int min, int max) override 2903 { 2904 m_xScale->SetRangeMin(min); 2905 m_xScale->SetRangeMax(max); 2906 } 2907 2908 virtual int get_value() const override { return m_xScale->GetThumbPos(); } 2909 2910 virtual void set_increments(int step, int page) override 2911 { 2912 m_xScale->SetLineSize(step); 2913 m_xScale->SetPageSize(page); 2914 } 2915 2916 virtual void get_increments(int& step, int& page) const override 2917 { 2918 step = m_xScale->GetLineSize(); 2919 page = m_xScale->GetPageSize(); 2920 } 2921 2922 virtual ~SalInstanceScale() override { m_xScale->SetSlideHdl(Link<Slider*, void>()); } 2923 }; 2924 2925 } 2926 2927 IMPL_LINK_NOARG(SalInstanceScale, SlideHdl, Slider*, void) { signal_value_changed(); } 2928 2929 namespace 2930 { 2931 class SalInstanceSpinner : public SalInstanceWidget, public virtual weld::Spinner 2932 { 2933 private: 2934 VclPtr<Throbber> m_xThrobber; 2935 2936 public: 2937 SalInstanceSpinner(Throbber* pThrobber, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2938 : SalInstanceWidget(pThrobber, pBuilder, bTakeOwnership) 2939 , m_xThrobber(pThrobber) 2940 { 2941 } 2942 2943 virtual void start() override { m_xThrobber->start(); } 2944 2945 virtual void stop() override { m_xThrobber->stop(); } 2946 }; 2947 2948 class SalInstanceProgressBar : public SalInstanceWidget, public virtual weld::ProgressBar 2949 { 2950 private: 2951 VclPtr<::ProgressBar> m_xProgressBar; 2952 2953 public: 2954 SalInstanceProgressBar(::ProgressBar* pProgressBar, SalInstanceBuilder* pBuilder, 2955 bool bTakeOwnership) 2956 : SalInstanceWidget(pProgressBar, pBuilder, bTakeOwnership) 2957 , m_xProgressBar(pProgressBar) 2958 { 2959 } 2960 2961 virtual void set_percentage(int value) override { m_xProgressBar->SetValue(value); } 2962 2963 virtual OUString get_text() const override { return m_xProgressBar->GetText(); } 2964 2965 virtual void set_text(const OUString& rText) override { m_xProgressBar->SetText(rText); } 2966 }; 2967 2968 class SalInstanceImage : public SalInstanceWidget, public virtual weld::Image 2969 { 2970 private: 2971 VclPtr<FixedImage> m_xImage; 2972 2973 public: 2974 SalInstanceImage(FixedImage* pImage, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 2975 : SalInstanceWidget(pImage, pBuilder, bTakeOwnership) 2976 , m_xImage(pImage) 2977 { 2978 } 2979 2980 virtual void set_from_icon_name(const OUString& rIconName) override 2981 { 2982 m_xImage->SetImage(::Image(StockImage::Yes, rIconName)); 2983 } 2984 2985 virtual void set_image(VirtualDevice* pDevice) override 2986 { 2987 if (pDevice) 2988 m_xImage->SetImage(createImage(*pDevice)); 2989 else 2990 m_xImage->SetImage(::Image()); 2991 } 2992 2993 virtual void set_image(const css::uno::Reference<css::graphic::XGraphic>& rImage) override 2994 { 2995 m_xImage->SetImage(::Image(rImage)); 2996 } 2997 }; 2998 2999 class SalInstanceCalendar : public SalInstanceWidget, public virtual weld::Calendar 3000 { 3001 private: 3002 VclPtr<::Calendar> m_xCalendar; 3003 3004 DECL_LINK(SelectHdl, ::Calendar*, void); 3005 DECL_LINK(ActivateHdl, ::Calendar*, void); 3006 3007 public: 3008 SalInstanceCalendar(::Calendar* pCalendar, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 3009 : SalInstanceWidget(pCalendar, pBuilder, bTakeOwnership) 3010 , m_xCalendar(pCalendar) 3011 { 3012 m_xCalendar->SetSelectHdl(LINK(this, SalInstanceCalendar, SelectHdl)); 3013 m_xCalendar->SetActivateHdl(LINK(this, SalInstanceCalendar, ActivateHdl)); 3014 } 3015 3016 virtual void set_date(const Date& rDate) override { m_xCalendar->SetCurDate(rDate); } 3017 3018 virtual Date get_date() const override { return m_xCalendar->GetFirstSelectedDate(); } 3019 3020 virtual ~SalInstanceCalendar() override 3021 { 3022 m_xCalendar->SetSelectHdl(Link<::Calendar*, void>()); 3023 m_xCalendar->SetActivateHdl(Link<::Calendar*, void>()); 3024 } 3025 }; 3026 3027 } 3028 3029 IMPL_LINK_NOARG(SalInstanceCalendar, SelectHdl, ::Calendar*, void) 3030 { 3031 if (notify_events_disabled()) 3032 return; 3033 signal_selected(); 3034 } 3035 3036 IMPL_LINK_NOARG(SalInstanceCalendar, ActivateHdl, ::Calendar*, void) 3037 { 3038 if (notify_events_disabled()) 3039 return; 3040 signal_activated(); 3041 } 3042 3043 WeldTextFilter::WeldTextFilter(Link<OUString&, bool>& rInsertTextHdl) 3044 : TextFilter(OUString()) 3045 , m_rInsertTextHdl(rInsertTextHdl) 3046 { 3047 } 3048 3049 OUString WeldTextFilter::filter(const OUString& rText) 3050 { 3051 if (!m_rInsertTextHdl.IsSet()) 3052 return rText; 3053 OUString sText(rText); 3054 const bool bContinue = m_rInsertTextHdl.Call(sText); 3055 if (!bContinue) 3056 return OUString(); 3057 return sText; 3058 } 3059 3060 SalInstanceEntry::SalInstanceEntry(Edit* pEntry, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 3061 : SalInstanceWidget(pEntry, pBuilder, bTakeOwnership) 3062 , m_xEntry(pEntry) 3063 , m_aTextFilter(m_aInsertTextHdl) 3064 { 3065 m_xEntry->SetModifyHdl(LINK(this, SalInstanceEntry, ChangeHdl)); 3066 m_xEntry->SetActivateHdl(LINK(this, SalInstanceEntry, ActivateHdl)); 3067 m_xEntry->SetTextFilter(&m_aTextFilter); 3068 } 3069 3070 void SalInstanceEntry::set_text(const OUString& rText) 3071 { 3072 disable_notify_events(); 3073 m_xEntry->SetText(rText); 3074 enable_notify_events(); 3075 } 3076 3077 OUString SalInstanceEntry::get_text() const 3078 { 3079 return m_xEntry->GetText(); 3080 } 3081 3082 void SalInstanceEntry::set_width_chars(int nChars) 3083 { 3084 m_xEntry->SetWidthInChars(nChars); 3085 } 3086 3087 int SalInstanceEntry::get_width_chars() const 3088 { 3089 return m_xEntry->GetWidthInChars(); 3090 } 3091 3092 void SalInstanceEntry::set_max_length(int nChars) 3093 { 3094 m_xEntry->SetMaxTextLen(nChars); 3095 } 3096 3097 void SalInstanceEntry::select_region(int nStartPos, int nEndPos) 3098 { 3099 disable_notify_events(); 3100 long nStart = nStartPos < 0 ? SELECTION_MAX : nStartPos; 3101 long nEnd = nEndPos < 0 ? SELECTION_MAX : nEndPos; 3102 m_xEntry->SetSelection(Selection(nStart, nEnd)); 3103 enable_notify_events(); 3104 } 3105 3106 bool SalInstanceEntry::get_selection_bounds(int& rStartPos, int& rEndPos) 3107 { 3108 const Selection& rSelection = m_xEntry->GetSelection(); 3109 rStartPos = rSelection.Min(); 3110 rEndPos = rSelection.Max(); 3111 return rSelection.Len(); 3112 } 3113 3114 void SalInstanceEntry::replace_selection(const OUString& rText) 3115 { 3116 m_xEntry->ReplaceSelected(rText); 3117 } 3118 3119 void SalInstanceEntry::set_position(int nCursorPos) 3120 { 3121 disable_notify_events(); 3122 if (nCursorPos < 0) 3123 m_xEntry->SetCursorAtLast(); 3124 else 3125 m_xEntry->SetSelection(Selection(nCursorPos, nCursorPos)); 3126 enable_notify_events(); 3127 } 3128 3129 int SalInstanceEntry::get_position() const 3130 { 3131 return m_xEntry->GetSelection().Max(); 3132 } 3133 3134 void SalInstanceEntry::set_editable(bool bEditable) 3135 { 3136 m_xEntry->SetReadOnly(!bEditable); 3137 } 3138 3139 bool SalInstanceEntry::get_editable() const 3140 { 3141 return !m_xEntry->IsReadOnly(); 3142 } 3143 3144 void SalInstanceEntry::set_overwrite_mode(bool bOn) 3145 { 3146 m_xEntry->SetInsertMode(!bOn); 3147 } 3148 3149 bool SalInstanceEntry::get_overwrite_mode() const 3150 { 3151 return !m_xEntry->IsInsertMode(); 3152 } 3153 3154 void SalInstanceEntry::set_message_type(weld::EntryMessageType eType) 3155 { 3156 switch (eType) 3157 { 3158 case weld::EntryMessageType::Normal: 3159 m_xEntry->SetForceControlBackground(false); 3160 m_xEntry->SetControlForeground(); 3161 m_xEntry->SetControlBackground(); 3162 break; 3163 case weld::EntryMessageType::Warning: 3164 // tdf#114603: enable setting the background to a different color; 3165 // relevant for GTK; see also #i75179# 3166 m_xEntry->SetForceControlBackground(true); 3167 m_xEntry->SetControlForeground(); 3168 m_xEntry->SetControlBackground(COL_YELLOW); 3169 break; 3170 case weld::EntryMessageType::Error: 3171 // tdf#114603: enable setting the background to a different color; 3172 // relevant for GTK; see also #i75179# 3173 m_xEntry->SetForceControlBackground(true); 3174 m_xEntry->SetControlForeground(COL_WHITE); 3175 m_xEntry->SetControlBackground(0xff6563); 3176 break; 3177 } 3178 } 3179 3180 void SalInstanceEntry::set_font(const vcl::Font& rFont) 3181 { 3182 m_xEntry->SetPointFont(*m_xEntry, rFont); 3183 m_xEntry->Invalidate(); 3184 } 3185 3186 void SalInstanceEntry::set_font_color(const Color& rColor) 3187 { 3188 if (rColor == COL_AUTO) 3189 m_xEntry->SetControlForeground(); 3190 else 3191 m_xEntry->SetControlForeground(rColor); 3192 } 3193 3194 void SalInstanceEntry::connect_cursor_position(const Link<Entry&, void>& rLink) 3195 { 3196 assert(!m_aCursorPositionHdl.IsSet()); 3197 m_xEntry->AddEventListener(LINK(this, SalInstanceEntry, CursorListener)); 3198 weld::Entry::connect_cursor_position(rLink); 3199 } 3200 3201 void SalInstanceEntry::set_placeholder_text(const OUString& rText) 3202 { 3203 m_xEntry->SetPlaceholderText(rText); 3204 } 3205 3206 Edit& SalInstanceEntry::getEntry() 3207 { 3208 return *m_xEntry; 3209 } 3210 3211 void SalInstanceEntry::fire_signal_changed() 3212 { 3213 signal_changed(); 3214 } 3215 3216 void SalInstanceEntry::cut_clipboard() 3217 { 3218 m_xEntry->Cut(); 3219 } 3220 3221 void SalInstanceEntry::copy_clipboard() 3222 { 3223 m_xEntry->Copy(); 3224 } 3225 3226 void SalInstanceEntry::paste_clipboard() 3227 { 3228 m_xEntry->Paste(); 3229 } 3230 3231 namespace 3232 { 3233 void set_alignment(Edit& rEntry, TxtAlign eXAlign) 3234 { 3235 WinBits nAlign(0); 3236 switch (eXAlign) 3237 { 3238 case TxtAlign::Left: 3239 nAlign = WB_LEFT; 3240 break; 3241 case TxtAlign::Center: 3242 nAlign = WB_CENTER; 3243 break; 3244 case TxtAlign::Right: 3245 nAlign = WB_RIGHT; 3246 break; 3247 } 3248 WinBits nBits = rEntry.GetStyle(); 3249 nBits &= ~(WB_LEFT | WB_CENTER | WB_RIGHT); 3250 rEntry.SetStyle(nBits | nAlign); 3251 } 3252 } 3253 3254 void SalInstanceEntry::set_alignment(TxtAlign eXAlign) 3255 { 3256 ::set_alignment(*m_xEntry, eXAlign); 3257 } 3258 3259 SalInstanceEntry::~SalInstanceEntry() 3260 { 3261 if (m_aCursorPositionHdl.IsSet()) 3262 m_xEntry->RemoveEventListener(LINK(this, SalInstanceEntry, CursorListener)); 3263 m_xEntry->SetTextFilter(nullptr); 3264 m_xEntry->SetActivateHdl(Link<Edit&, bool>()); 3265 m_xEntry->SetModifyHdl(Link<Edit&, void>()); 3266 } 3267 3268 IMPL_LINK_NOARG(SalInstanceEntry, ChangeHdl, Edit&, void) { signal_changed(); } 3269 3270 IMPL_LINK(SalInstanceEntry, CursorListener, VclWindowEvent&, rEvent, void) 3271 { 3272 if (notify_events_disabled()) 3273 return; 3274 if (rEvent.GetId() == VclEventId::EditSelectionChanged 3275 || rEvent.GetId() == VclEventId::EditCaretChanged) 3276 signal_cursor_position(); 3277 } 3278 3279 IMPL_LINK_NOARG(SalInstanceEntry, ActivateHdl, Edit&, bool) { return m_aActivateHdl.Call(*this); } 3280 3281 namespace 3282 { 3283 struct SalInstanceTreeIter : public weld::TreeIter 3284 { 3285 SalInstanceTreeIter(const SalInstanceTreeIter* pOrig) 3286 : iter(pOrig ? pOrig->iter : nullptr) 3287 { 3288 } 3289 SalInstanceTreeIter(SvTreeListEntry* pIter) 3290 : iter(pIter) 3291 { 3292 } 3293 virtual bool equal(const TreeIter& rOther) const override 3294 { 3295 return iter == static_cast<const SalInstanceTreeIter&>(rOther).iter; 3296 } 3297 SvTreeListEntry* iter; 3298 }; 3299 3300 } 3301 3302 class SalInstanceTreeView; 3303 3304 static SalInstanceTreeView* g_DragSource; 3305 3306 class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView 3307 { 3308 private: 3309 // owner for UserData 3310 std::vector<std::unique_ptr<OUString>> m_aUserData; 3311 VclPtr<SvTabListBox> m_xTreeView; 3312 SvLBoxButtonData m_aCheckButtonData; 3313 SvLBoxButtonData m_aRadioButtonData; 3314 // currently expanding parent that logically, but not currently physically, 3315 // contain placeholders 3316 o3tl::sorted_vector<SvTreeListEntry*> m_aExpandingPlaceHolderParents; 3317 // which columns should be custom rendered 3318 o3tl::sorted_vector<int> m_aCustomRenders; 3319 bool m_bTogglesAsRadio; 3320 int m_nSortColumn; 3321 3322 DECL_LINK(SelectHdl, SvTreeListBox*, void); 3323 DECL_LINK(DeSelectHdl, SvTreeListBox*, void); 3324 DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool); 3325 DECL_LINK(ExpandingHdl, SvTreeListBox*, bool); 3326 DECL_LINK(EndDragHdl, HeaderBar*, void); 3327 DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void); 3328 DECL_LINK(ToggleHdl, SvLBoxButtonData*, void); 3329 DECL_LINK(ModelChangedHdl, SvTreeListBox*, void); 3330 DECL_LINK(StartDragHdl, SvTreeListBox*, bool); 3331 DECL_STATIC_LINK(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void); 3332 DECL_LINK(EditingEntryHdl, SvTreeListEntry*, bool); 3333 typedef std::pair<SvTreeListEntry*, OUString> IterString; 3334 DECL_LINK(EditedEntryHdl, IterString, bool); 3335 DECL_LINK(VisibleRangeChangedHdl, SvTreeListBox*, void); 3336 DECL_LINK(CompareHdl, const SvSortData&, sal_Int32); 3337 DECL_LINK(PopupMenuHdl, const CommandEvent&, bool); 3338 DECL_LINK(TooltipHdl, const HelpEvent&, bool); 3339 DECL_LINK(CustomRenderHdl, svtree_render_args, void); 3340 DECL_LINK(CustomMeasureHdl, svtree_measure_args, Size); 3341 3342 // Each row has a cell for the expander image, (and an optional cell for a 3343 // checkbutton if enable_toggle_buttons has been called) which precede 3344 // index 0 3345 int to_internal_model(int col) const 3346 { 3347 if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN) 3348 ++col; // skip checkbutton column 3349 ++col; //skip expander column 3350 return col; 3351 } 3352 3353 int to_external_model(int col) const 3354 { 3355 if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN) 3356 --col; // skip checkbutton column 3357 --col; //skip expander column 3358 return col; 3359 } 3360 3361 bool IsDummyEntry(SvTreeListEntry* pEntry) const 3362 { 3363 return m_xTreeView->GetEntryText(pEntry).trim() == "<dummy>"; 3364 } 3365 3366 SvTreeListEntry* GetPlaceHolderChild(SvTreeListEntry* pEntry) const 3367 { 3368 if (pEntry->HasChildren()) 3369 { 3370 auto pChild = m_xTreeView->FirstChild(pEntry); 3371 assert(pChild); 3372 if (IsDummyEntry(pChild)) 3373 return pChild; 3374 } 3375 return nullptr; 3376 } 3377 3378 static void set_font_color(SvTreeListEntry* pEntry, const Color& rColor) 3379 { 3380 if (rColor == COL_AUTO) 3381 pEntry->SetTextColor(std::optional<Color>()); 3382 else 3383 pEntry->SetTextColor(rColor); 3384 } 3385 3386 void AddStringItem(SvTreeListEntry* pEntry, const OUString& rStr, int nCol) 3387 { 3388 auto xCell = std::make_unique<SvLBoxString>(rStr); 3389 if (m_aCustomRenders.count(nCol)) 3390 xCell->SetCustomRender(); 3391 pEntry->AddItem(std::move(xCell)); 3392 } 3393 3394 void do_insert(const weld::TreeIter* pParent, int pos, const OUString* pStr, 3395 const OUString* pId, const OUString* pIconName, 3396 VirtualDevice* pImageSurface, bool bChildrenOnDemand, 3397 weld::TreeIter* pRet, bool bIsSeparator) 3398 { 3399 disable_notify_events(); 3400 const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent); 3401 SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr; 3402 auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos; 3403 void* pUserData; 3404 if (pId) 3405 { 3406 m_aUserData.emplace_back(std::make_unique<OUString>(*pId)); 3407 pUserData = m_aUserData.back().get(); 3408 } 3409 else 3410 pUserData = nullptr; 3411 3412 SvTreeListEntry* pEntry = new SvTreeListEntry; 3413 if (bIsSeparator) 3414 pEntry->SetFlags(pEntry->GetFlags() | SvTLEntryFlags::IS_SEPARATOR); 3415 3416 if (m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN) 3417 AddStringItem(pEntry, "", -1); 3418 3419 if (pIconName || pImageSurface) 3420 { 3421 Image aImage(pIconName ? createImage(*pIconName) : createImage(*pImageSurface)); 3422 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false)); 3423 } 3424 else 3425 { 3426 Image aDummy; 3427 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false)); 3428 } 3429 if (pStr) 3430 AddStringItem(pEntry, *pStr, 0); 3431 pEntry->SetUserData(pUserData); 3432 m_xTreeView->Insert(pEntry, iter, nInsertPos); 3433 3434 if (pRet) 3435 { 3436 SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet); 3437 pVclRetIter->iter = pEntry; 3438 } 3439 3440 if (bChildrenOnDemand) 3441 { 3442 SvTreeListEntry* pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr); 3443 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder); 3444 pViewData->SetSelectable(false); 3445 } 3446 3447 if (bIsSeparator) 3448 { 3449 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry); 3450 pViewData->SetSelectable(false); 3451 } 3452 3453 enable_notify_events(); 3454 } 3455 3456 void update_checkbutton_column_width(SvTreeListEntry* pEntry) 3457 { 3458 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry); 3459 m_xTreeView->InitViewData(pViewData, pEntry); 3460 m_xTreeView->CheckBoxInserted(pEntry); 3461 } 3462 3463 void do_set_toggle(SvTreeListEntry* pEntry, TriState eState, int col) 3464 { 3465 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 3466 // if its the placeholder to allow a blank column, replace it now 3467 if (pEntry->GetItem(col).GetType() != SvLBoxItemType::Button) 3468 { 3469 SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData; 3470 pEntry->ReplaceItem(std::make_unique<SvLBoxButton>(pData), 0); 3471 update_checkbutton_column_width(pEntry); 3472 3473 } 3474 SvLBoxItem& rItem = pEntry->GetItem(col); 3475 assert(dynamic_cast<SvLBoxButton*>(&rItem)); 3476 switch (eState) 3477 { 3478 case TRISTATE_TRUE: 3479 static_cast<SvLBoxButton&>(rItem).SetStateChecked(); 3480 break; 3481 case TRISTATE_FALSE: 3482 static_cast<SvLBoxButton&>(rItem).SetStateUnchecked(); 3483 break; 3484 case TRISTATE_INDET: 3485 static_cast<SvLBoxButton&>(rItem).SetStateTristate(); 3486 break; 3487 } 3488 3489 m_xTreeView->ModelHasEntryInvalidated(pEntry); 3490 } 3491 3492 static TriState do_get_toggle(SvTreeListEntry* pEntry, int col) 3493 { 3494 if (static_cast<size_t>(col) == pEntry->ItemCount()) 3495 return TRISTATE_FALSE; 3496 3497 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 3498 SvLBoxItem& rItem = pEntry->GetItem(col); 3499 assert(dynamic_cast<SvLBoxButton*>(&rItem)); 3500 SvLBoxButton& rToggle = static_cast<SvLBoxButton&>(rItem); 3501 if (rToggle.IsStateTristate()) 3502 return TRISTATE_INDET; 3503 else if (rToggle.IsStateChecked()) 3504 return TRISTATE_TRUE; 3505 return TRISTATE_FALSE; 3506 } 3507 3508 TriState get_toggle(SvTreeListEntry* pEntry, int col) const 3509 { 3510 if (col == -1) 3511 { 3512 assert(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN); 3513 return do_get_toggle(pEntry, 0); 3514 } 3515 col = to_internal_model(col); 3516 return do_get_toggle(pEntry, col); 3517 } 3518 3519 void set_toggle(SvTreeListEntry* pEntry, TriState eState, int col) 3520 { 3521 if (col == -1) 3522 { 3523 assert(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN); 3524 do_set_toggle(pEntry, eState, 0); 3525 return; 3526 } 3527 3528 col = to_internal_model(col); 3529 3530 // blank out missing entries 3531 for (int i = pEntry->ItemCount(); i < col; ++i) 3532 AddStringItem(pEntry, "", i - 1); 3533 3534 if (static_cast<size_t>(col) == pEntry->ItemCount()) 3535 { 3536 SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData; 3537 pEntry->AddItem(std::make_unique<SvLBoxButton>(pData)); 3538 update_checkbutton_column_width(pEntry); 3539 } 3540 3541 do_set_toggle(pEntry, eState, col); 3542 } 3543 3544 bool get_text_emphasis(SvTreeListEntry* pEntry, int col) const 3545 { 3546 col = to_internal_model(col); 3547 3548 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 3549 SvLBoxItem& rItem = pEntry->GetItem(col); 3550 assert(dynamic_cast<SvLBoxString*>(&rItem)); 3551 return static_cast<SvLBoxString&>(rItem).IsEmphasized(); 3552 } 3553 3554 public: 3555 SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 3556 : SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership) 3557 , m_xTreeView(pTreeView) 3558 , m_aCheckButtonData(pTreeView, false) 3559 , m_aRadioButtonData(pTreeView, true) 3560 , m_bTogglesAsRadio(false) 3561 , m_nSortColumn(-1) 3562 { 3563 m_xTreeView->SetNodeDefaultImages(); 3564 m_xTreeView->SetForceMakeVisible(true); 3565 m_xTreeView->SetSelectHdl(LINK(this, SalInstanceTreeView, SelectHdl)); 3566 m_xTreeView->SetDeselectHdl(LINK(this, SalInstanceTreeView, DeSelectHdl)); 3567 m_xTreeView->SetDoubleClickHdl(LINK(this, SalInstanceTreeView, DoubleClickHdl)); 3568 m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl)); 3569 m_xTreeView->SetPopupMenuHdl(LINK(this, SalInstanceTreeView, PopupMenuHdl)); 3570 m_xTreeView->SetCustomRenderHdl(LINK(this, SalInstanceTreeView, CustomRenderHdl)); 3571 m_xTreeView->SetCustomMeasureHdl(LINK(this, SalInstanceTreeView, CustomMeasureHdl)); 3572 const long aTabPositions[] = { 0 }; 3573 m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions); 3574 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 3575 3576 if (pHeaderBox) 3577 { 3578 if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar()) 3579 { 3580 //make the last entry fill available space 3581 pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1), 3582 HEADERBAR_FULLSIZE); 3583 pHeaderBar->SetEndDragHdl(LINK(this, SalInstanceTreeView, EndDragHdl)); 3584 pHeaderBar->SetSelectHdl(LINK(this, SalInstanceTreeView, HeaderBarClickedHdl)); 3585 } 3586 pHeaderBox->SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl)); 3587 pHeaderBox->SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl)); 3588 } 3589 else 3590 { 3591 static_cast<LclTabListBox&>(*m_xTreeView) 3592 .SetModelChangedHdl(LINK(this, SalInstanceTreeView, ModelChangedHdl)); 3593 static_cast<LclTabListBox&>(*m_xTreeView) 3594 .SetStartDragHdl(LINK(this, SalInstanceTreeView, StartDragHdl)); 3595 static_cast<LclTabListBox&>(*m_xTreeView) 3596 .SetEndDragHdl(LINK(this, SalInstanceTreeView, FinishDragHdl)); 3597 static_cast<LclTabListBox&>(*m_xTreeView) 3598 .SetEditingEntryHdl(LINK(this, SalInstanceTreeView, EditingEntryHdl)); 3599 static_cast<LclTabListBox&>(*m_xTreeView) 3600 .SetEditedEntryHdl(LINK(this, SalInstanceTreeView, EditedEntryHdl)); 3601 } 3602 m_aCheckButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl)); 3603 m_aRadioButtonData.SetLink(LINK(this, SalInstanceTreeView, ToggleHdl)); 3604 } 3605 3606 virtual void connect_query_tooltip(const Link<const weld::TreeIter&, OUString>& rLink) override 3607 { 3608 weld::TreeView::connect_query_tooltip(rLink); 3609 m_xTreeView->SetTooltipHdl(LINK(this, SalInstanceTreeView, TooltipHdl)); 3610 } 3611 3612 virtual void columns_autosize() override 3613 { 3614 std::vector<long> aWidths; 3615 m_xTreeView->getPreferredDimensions(aWidths); 3616 if (aWidths.size() > 2) 3617 { 3618 std::vector<int> aColWidths; 3619 for (size_t i = 1; i < aWidths.size() - 1; ++i) 3620 aColWidths.push_back(aWidths[i] - aWidths[i - 1]); 3621 set_column_fixed_widths(aColWidths); 3622 } 3623 } 3624 3625 virtual void freeze() override 3626 { 3627 SalInstanceWidget::freeze(); 3628 m_xTreeView->SetUpdateMode(false); 3629 m_xTreeView->GetModel()->EnableInvalidate(false); 3630 } 3631 3632 virtual void thaw() override 3633 { 3634 m_xTreeView->GetModel()->EnableInvalidate(true); 3635 m_xTreeView->SetUpdateMode(true); 3636 SalInstanceWidget::thaw(); 3637 } 3638 3639 virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override 3640 { 3641 std::vector<long> aTabPositions; 3642 aTabPositions.push_back(0); 3643 for (size_t i = 0; i < rWidths.size(); ++i) 3644 aTabPositions.push_back(aTabPositions[i] + rWidths[i]); 3645 m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel); 3646 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 3647 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) 3648 { 3649 for (size_t i = 0; i < rWidths.size(); ++i) 3650 pHeaderBar->SetItemSize(pHeaderBar->GetItemId(i), rWidths[i]); 3651 } 3652 // call Resize to recalculate based on the new tabs 3653 m_xTreeView->Resize(); 3654 } 3655 3656 virtual void set_column_editables(const std::vector<bool>& rEditables) override 3657 { 3658 size_t nTabCount = rEditables.size(); 3659 for (size_t i = 0 ; i < nTabCount; ++i) 3660 m_xTreeView->SetTabEditable(i, rEditables[i]); 3661 } 3662 3663 virtual void set_centered_column(int nCol) override 3664 { 3665 m_xTreeView->SetTabJustify(nCol, SvTabJustify::AdjustCenter); 3666 } 3667 3668 virtual int get_column_width(int nColumn) const override 3669 { 3670 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 3671 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) 3672 return pHeaderBar->GetItemSize(pHeaderBar->GetItemId(nColumn)); 3673 // GetTab(0) gives the position of the bitmap which is automatically inserted by the TabListBox. 3674 // So the first text column's width is Tab(2)-Tab(1). 3675 auto nWidthPixel 3676 = m_xTreeView->GetLogicTab(nColumn + 2) - m_xTreeView->GetLogicTab(nColumn + 1); 3677 nWidthPixel -= SV_TAB_BORDER; 3678 return nWidthPixel; 3679 } 3680 3681 virtual OUString get_column_title(int nColumn) const override 3682 { 3683 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 3684 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) 3685 { 3686 return pHeaderBar->GetItemText(pHeaderBar->GetItemId(nColumn)); 3687 } 3688 return OUString(); 3689 } 3690 3691 virtual void set_column_title(int nColumn, const OUString& rTitle) override 3692 { 3693 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 3694 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) 3695 { 3696 return pHeaderBar->SetItemText(pHeaderBar->GetItemId(nColumn), rTitle); 3697 } 3698 } 3699 3700 virtual void set_column_custom_renderer(int nColumn, bool bEnable) override 3701 { 3702 assert(n_children() == 0 && "tree must be empty"); 3703 if (bEnable) 3704 m_aCustomRenders.insert(nColumn); 3705 else 3706 m_aCustomRenders.erase(nColumn); 3707 } 3708 3709 virtual void queue_draw() override 3710 { 3711 // invalidate the entries 3712 SvTreeList* pModel = m_xTreeView->GetModel(); 3713 for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; pEntry = m_xTreeView->Next(pEntry)) 3714 pModel->InvalidateEntry(pEntry); 3715 } 3716 3717 virtual void show() override 3718 { 3719 if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get())) 3720 pHeaderBox->GetParent()->Show(); 3721 SalInstanceContainer::show(); 3722 } 3723 3724 virtual void hide() override 3725 { 3726 if (LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get())) 3727 pHeaderBox->GetParent()->Hide(); 3728 SalInstanceContainer::hide(); 3729 } 3730 3731 virtual void insert(const weld::TreeIter* pParent, int pos, const OUString* pStr, 3732 const OUString* pId, const OUString* pIconName, 3733 VirtualDevice* pImageSurface, bool bChildrenOnDemand, 3734 weld::TreeIter* pRet) override 3735 { 3736 do_insert(pParent, pos, pStr, pId, pIconName, pImageSurface, 3737 bChildrenOnDemand, pRet, false); 3738 } 3739 3740 virtual void insert_separator(int pos, const OUString& /*rId*/) override 3741 { 3742 OUString sSep(VclResId(STR_SEPARATOR)); 3743 do_insert(nullptr, pos, &sSep, nullptr, nullptr, nullptr, 3744 false, nullptr, true); 3745 } 3746 3747 virtual void 3748 bulk_insert_for_each(int nSourceCount, 3749 const std::function<void(weld::TreeIter&, int nSourceIndex)>& func, 3750 const std::vector<int>* pFixedWidths) override 3751 { 3752 freeze(); 3753 clear(); 3754 SalInstanceTreeIter aVclIter(static_cast<SvTreeListEntry*>(nullptr)); 3755 3756 m_xTreeView->nTreeFlags |= SvTreeFlags::MANINS; 3757 3758 if (pFixedWidths) 3759 set_column_fixed_widths(*pFixedWidths); 3760 3761 bool bHasAutoCheckButton(m_xTreeView->nTreeFlags & SvTreeFlags::CHKBTN); 3762 size_t nExtraCols = bHasAutoCheckButton ? 2 : 1; 3763 3764 Image aDummy; 3765 for (int i = 0; i < nSourceCount; ++i) 3766 { 3767 aVclIter.iter = new SvTreeListEntry; 3768 if (bHasAutoCheckButton) 3769 AddStringItem(aVclIter.iter, "", -1); 3770 aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false)); 3771 m_xTreeView->Insert(aVclIter.iter, nullptr, TREELIST_APPEND); 3772 func(aVclIter, i); 3773 3774 if (!pFixedWidths) 3775 continue; 3776 3777 size_t nFixedWidths = std::min(pFixedWidths->size(), aVclIter.iter->ItemCount()); 3778 for (size_t j = 0; j < nFixedWidths; ++j) 3779 { 3780 SvLBoxItem& rItem = aVclIter.iter->GetItem(j + nExtraCols); 3781 SvViewDataItem* pViewDataItem = m_xTreeView->GetViewDataItem(aVclIter.iter, &rItem); 3782 pViewDataItem->mnWidth = (*pFixedWidths)[j]; 3783 } 3784 } 3785 3786 m_xTreeView->nTreeFlags &= ~SvTreeFlags::MANINS; 3787 3788 thaw(); 3789 } 3790 3791 virtual void set_font_color(int pos, const Color& rColor) override 3792 { 3793 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3794 set_font_color(pEntry, rColor); 3795 } 3796 3797 virtual void set_font_color(const weld::TreeIter& rIter, const Color& rColor) override 3798 { 3799 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 3800 set_font_color(rVclIter.iter, rColor); 3801 } 3802 3803 virtual void remove(int pos) override 3804 { 3805 disable_notify_events(); 3806 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3807 m_xTreeView->RemoveEntry(pEntry); 3808 enable_notify_events(); 3809 } 3810 3811 virtual int find_text(const OUString& rText) const override 3812 { 3813 for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; 3814 pEntry = m_xTreeView->Next(pEntry)) 3815 { 3816 if (SvTabListBox::GetEntryText(pEntry, 0) == rText) 3817 return SvTreeList::GetRelPos(pEntry); 3818 } 3819 return -1; 3820 } 3821 3822 virtual int find_id(const OUString& rId) const override 3823 { 3824 for (SvTreeListEntry* pEntry = m_xTreeView->First(); pEntry; 3825 pEntry = m_xTreeView->Next(pEntry)) 3826 { 3827 const OUString* pId = static_cast<const OUString*>(pEntry->GetUserData()); 3828 if (!pId) 3829 continue; 3830 if (rId == *pId) 3831 return SvTreeList::GetRelPos(pEntry); 3832 } 3833 return -1; 3834 } 3835 3836 virtual void swap(int pos1, int pos2) override 3837 { 3838 int min = std::min(pos1, pos2); 3839 int max = std::max(pos1, pos2); 3840 SvTreeList* pModel = m_xTreeView->GetModel(); 3841 SvTreeListEntry* pEntry1 = pModel->GetEntry(nullptr, min); 3842 SvTreeListEntry* pEntry2 = pModel->GetEntry(nullptr, max); 3843 pModel->Move(pEntry1, pEntry2); 3844 } 3845 3846 virtual void clear() override 3847 { 3848 disable_notify_events(); 3849 m_xTreeView->Clear(); 3850 m_aUserData.clear(); 3851 enable_notify_events(); 3852 } 3853 3854 virtual int n_children() const override 3855 { 3856 return m_xTreeView->GetModel()->GetChildList(nullptr).size(); 3857 } 3858 3859 virtual int iter_n_children(const weld::TreeIter& rIter) const override 3860 { 3861 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 3862 return m_xTreeView->GetModel()->GetChildList(rVclIter.iter).size(); 3863 } 3864 3865 virtual void select(int pos) override 3866 { 3867 assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 3868 disable_notify_events(); 3869 if (pos == -1 || (pos == 0 && n_children() == 0)) 3870 m_xTreeView->SelectAll(false); 3871 else 3872 { 3873 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3874 m_xTreeView->Select(pEntry, true); 3875 m_xTreeView->MakeVisible(pEntry); 3876 } 3877 enable_notify_events(); 3878 } 3879 3880 virtual int get_cursor_index() const override 3881 { 3882 SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry(); 3883 if (!pEntry) 3884 return -1; 3885 return SvTreeList::GetRelPos(pEntry); 3886 } 3887 3888 virtual void set_cursor(int pos) override 3889 { 3890 disable_notify_events(); 3891 if (pos == -1) 3892 m_xTreeView->SetCurEntry(nullptr); 3893 else 3894 { 3895 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3896 m_xTreeView->SetCurEntry(pEntry); 3897 } 3898 enable_notify_events(); 3899 } 3900 3901 virtual void scroll_to_row(int pos) override 3902 { 3903 assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 3904 disable_notify_events(); 3905 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3906 m_xTreeView->MakeVisible(pEntry); 3907 enable_notify_events(); 3908 } 3909 3910 virtual bool is_selected(int pos) const override 3911 { 3912 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3913 return m_xTreeView->IsSelected(pEntry); 3914 } 3915 3916 virtual void unselect(int pos) override 3917 { 3918 assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 3919 disable_notify_events(); 3920 if (pos == -1) 3921 m_xTreeView->SelectAll(true); 3922 else 3923 { 3924 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3925 m_xTreeView->Select(pEntry, false); 3926 } 3927 enable_notify_events(); 3928 } 3929 3930 virtual std::vector<int> get_selected_rows() const override 3931 { 3932 std::vector<int> aRows; 3933 3934 aRows.reserve(m_xTreeView->GetSelectionCount()); 3935 for (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); pEntry; 3936 pEntry = m_xTreeView->NextSelected(pEntry)) 3937 aRows.push_back(SvTreeList::GetRelPos(pEntry)); 3938 3939 return aRows; 3940 } 3941 3942 OUString get_text(SvTreeListEntry* pEntry, int col) const 3943 { 3944 if (col == -1) 3945 return SvTabListBox::GetEntryText(pEntry, 0); 3946 3947 col = to_internal_model(col); 3948 3949 if (static_cast<size_t>(col) == pEntry->ItemCount()) 3950 return OUString(); 3951 3952 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 3953 SvLBoxItem& rItem = pEntry->GetItem(col); 3954 assert(dynamic_cast<SvLBoxString*>(&rItem)); 3955 return static_cast<SvLBoxString&>(rItem).GetText(); 3956 } 3957 3958 virtual OUString get_text(int pos, int col) const override 3959 { 3960 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3961 return get_text(pEntry, col); 3962 } 3963 3964 void set_text(SvTreeListEntry* pEntry, const OUString& rText, int col) 3965 { 3966 if (col == -1) 3967 { 3968 m_xTreeView->SetEntryText(pEntry, rText); 3969 return; 3970 } 3971 3972 col = to_internal_model(col); 3973 3974 // blank out missing entries 3975 for (int i = pEntry->ItemCount(); i < col; ++i) 3976 AddStringItem(pEntry, "", i - 1); 3977 3978 if (static_cast<size_t>(col) == pEntry->ItemCount()) 3979 { 3980 AddStringItem(pEntry, rText, col - 1); 3981 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry); 3982 m_xTreeView->InitViewData(pViewData, pEntry); 3983 } 3984 else 3985 { 3986 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 3987 SvLBoxItem& rItem = pEntry->GetItem(col); 3988 assert(dynamic_cast<SvLBoxString*>(&rItem)); 3989 static_cast<SvLBoxString&>(rItem).SetText(rText); 3990 } 3991 m_xTreeView->ModelHasEntryInvalidated(pEntry); 3992 } 3993 3994 virtual void set_text(int pos, const OUString& rText, int col) override 3995 { 3996 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 3997 set_text(pEntry, rText, col); 3998 } 3999 4000 void set_sensitive(SvTreeListEntry* pEntry, bool bSensitive, int col) 4001 { 4002 if (col == -1) 4003 { 4004 auto nFlags = pEntry->GetFlags() & ~SvTLEntryFlags::SEMITRANSPARENT; 4005 if (!bSensitive) 4006 nFlags = nFlags | SvTLEntryFlags::SEMITRANSPARENT; 4007 pEntry->SetFlags(nFlags); 4008 const sal_uInt16 nCount = pEntry->ItemCount(); 4009 for (sal_uInt16 nCur = 0; nCur < nCount; ++nCur) 4010 { 4011 SvLBoxItem& rItem = pEntry->GetItem(nCur); 4012 if (rItem.GetType() == SvLBoxItemType::String) 4013 { 4014 rItem.Enable(bSensitive); 4015 m_xTreeView->ModelHasEntryInvalidated(pEntry); 4016 break; 4017 } 4018 } 4019 return; 4020 } 4021 4022 col = to_internal_model(col); 4023 4024 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 4025 SvLBoxItem& rItem = pEntry->GetItem(col); 4026 rItem.Enable(bSensitive); 4027 4028 m_xTreeView->ModelHasEntryInvalidated(pEntry); 4029 } 4030 4031 using SalInstanceWidget::set_sensitive; 4032 4033 virtual void set_sensitive(int pos, bool bSensitive, int col) override 4034 { 4035 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4036 set_sensitive(pEntry, bSensitive, col); 4037 } 4038 4039 virtual void set_sensitive(const weld::TreeIter& rIter, bool bSensitive, int col) override 4040 { 4041 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4042 set_sensitive(rVclIter.iter, bSensitive, col); 4043 } 4044 4045 virtual TriState get_toggle(int pos, int col) const override 4046 { 4047 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4048 return get_toggle(pEntry, col); 4049 } 4050 4051 virtual TriState get_toggle(const weld::TreeIter& rIter, int col) const override 4052 { 4053 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4054 return get_toggle(rVclIter.iter, col); 4055 } 4056 4057 virtual void enable_toggle_buttons(weld::ColumnToggleType eType) override 4058 { 4059 assert(n_children() == 0 && "tree must be empty"); 4060 m_bTogglesAsRadio = eType == weld::ColumnToggleType::Radio; 4061 4062 SvLBoxButtonData* pData = m_bTogglesAsRadio ? &m_aRadioButtonData : &m_aCheckButtonData; 4063 m_xTreeView->EnableCheckButton(pData); 4064 // EnableCheckButton clobbered this, restore it 4065 pData->SetLink(LINK(this, SalInstanceTreeView, ToggleHdl)); 4066 } 4067 4068 virtual void set_toggle(int pos, TriState eState, int col) override 4069 { 4070 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4071 set_toggle(pEntry, eState, col); 4072 } 4073 4074 virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override 4075 { 4076 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4077 set_toggle(rVclIter.iter, eState, col); 4078 } 4079 4080 virtual void set_extra_row_indent(const weld::TreeIter& rIter, int nIndentLevel) override 4081 { 4082 weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter); 4083 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter); 4084 rVclIter.iter->SetExtraIndent(nIndentLevel); 4085 } 4086 4087 void set_text_emphasis(SvTreeListEntry* pEntry, bool bOn, int col) 4088 { 4089 col = to_internal_model(col); 4090 4091 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 4092 SvLBoxItem& rItem = pEntry->GetItem(col); 4093 assert(dynamic_cast<SvLBoxString*>(&rItem)); 4094 static_cast<SvLBoxString&>(rItem).Emphasize(bOn); 4095 4096 m_xTreeView->ModelHasEntryInvalidated(pEntry); 4097 } 4098 4099 virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override 4100 { 4101 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4102 set_text_emphasis(rVclIter.iter, bOn, col); 4103 } 4104 4105 virtual void set_text_emphasis(int pos, bool bOn, int col) override 4106 { 4107 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4108 set_text_emphasis(pEntry, bOn, col); 4109 } 4110 4111 virtual bool get_text_emphasis(const weld::TreeIter& rIter, int col) const override 4112 { 4113 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4114 return get_text_emphasis(rVclIter.iter, col); 4115 } 4116 4117 virtual bool get_text_emphasis(int pos, int col) const override 4118 { 4119 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4120 return get_text_emphasis(pEntry, col); 4121 } 4122 4123 void set_text_align(SvTreeListEntry* pEntry, double fAlign, int col) 4124 { 4125 col = to_internal_model(col); 4126 4127 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 4128 SvLBoxItem& rItem = pEntry->GetItem(col); 4129 assert(dynamic_cast<SvLBoxString*>(&rItem)); 4130 static_cast<SvLBoxString&>(rItem).Align(fAlign); 4131 4132 m_xTreeView->ModelHasEntryInvalidated(pEntry); 4133 } 4134 4135 virtual void set_text_align(const weld::TreeIter& rIter, double fAlign, int col) override 4136 { 4137 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4138 set_text_align(rVclIter.iter, fAlign, col); 4139 } 4140 4141 virtual void set_text_align(int pos, double fAlign, int col) override 4142 { 4143 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4144 set_text_align(pEntry, fAlign, col); 4145 } 4146 4147 virtual void connect_editing( 4148 const Link<const weld::TreeIter&, bool>& rStartLink, 4149 const Link<const iter_string&, bool>& rEndLink) override 4150 { 4151 m_xTreeView->EnableInplaceEditing(rStartLink.IsSet() || rEndLink.IsSet()); 4152 weld::TreeView::connect_editing(rStartLink, rEndLink); 4153 } 4154 4155 virtual void start_editing(const weld::TreeIter& rIter) override 4156 { 4157 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4158 m_xTreeView->EditEntry(rVclIter.iter); 4159 } 4160 4161 virtual void end_editing() override { m_xTreeView->EndEditing(); } 4162 4163 void set_image(SvTreeListEntry* pEntry, const Image& rImage, int col) 4164 { 4165 if (col == -1) 4166 { 4167 m_xTreeView->SetExpandedEntryBmp(pEntry, rImage); 4168 m_xTreeView->SetCollapsedEntryBmp(pEntry, rImage); 4169 return; 4170 } 4171 4172 col = to_internal_model(col); 4173 4174 // blank out missing entries 4175 for (int i = pEntry->ItemCount(); i < col; ++i) 4176 AddStringItem(pEntry, "", i - 1); 4177 4178 if (static_cast<size_t>(col) == pEntry->ItemCount()) 4179 { 4180 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(rImage, rImage, false)); 4181 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry); 4182 m_xTreeView->InitViewData(pViewData, pEntry); 4183 } 4184 else 4185 { 4186 assert(col >= 0 && o3tl::make_unsigned(col) < pEntry->ItemCount()); 4187 SvLBoxItem& rItem = pEntry->GetItem(col); 4188 assert(dynamic_cast<SvLBoxContextBmp*>(&rItem)); 4189 static_cast<SvLBoxContextBmp&>(rItem).SetBitmap1(rImage); 4190 static_cast<SvLBoxContextBmp&>(rItem).SetBitmap2(rImage); 4191 } 4192 4193 m_xTreeView->SetEntryHeight(pEntry); 4194 m_xTreeView->ModelHasEntryInvalidated(pEntry); 4195 } 4196 4197 virtual void set_image(int pos, const OUString& rImage, int col) override 4198 { 4199 set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col); 4200 } 4201 4202 virtual void set_image(int pos, const css::uno::Reference<css::graphic::XGraphic>& rImage, 4203 int col) override 4204 { 4205 set_image(m_xTreeView->GetEntry(nullptr, pos), Image(rImage), col); 4206 } 4207 4208 virtual void set_image(int pos, VirtualDevice& rImage, int col) override 4209 { 4210 set_image(m_xTreeView->GetEntry(nullptr, pos), createImage(rImage), col); 4211 } 4212 4213 virtual void set_image(const weld::TreeIter& rIter, const OUString& rImage, int col) override 4214 { 4215 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4216 set_image(rVclIter.iter, createImage(rImage), col); 4217 } 4218 4219 virtual void set_image(const weld::TreeIter& rIter, 4220 const css::uno::Reference<css::graphic::XGraphic>& rImage, 4221 int col) override 4222 { 4223 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4224 set_image(rVclIter.iter, Image(rImage), col); 4225 } 4226 4227 virtual void set_image(const weld::TreeIter& rIter, VirtualDevice& rImage, int col) override 4228 { 4229 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4230 set_image(rVclIter.iter, createImage(rImage), col); 4231 } 4232 4233 const OUString* getEntryData(int index) const 4234 { 4235 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, index); 4236 return pEntry ? static_cast<const OUString*>(pEntry->GetUserData()) : nullptr; 4237 } 4238 4239 virtual OUString get_id(int pos) const override 4240 { 4241 const OUString* pRet = getEntryData(pos); 4242 if (!pRet) 4243 return OUString(); 4244 return *pRet; 4245 } 4246 4247 void set_id(SvTreeListEntry* pEntry, const OUString& rId) 4248 { 4249 m_aUserData.emplace_back(std::make_unique<OUString>(rId)); 4250 pEntry->SetUserData(m_aUserData.back().get()); 4251 } 4252 4253 virtual void set_id(int pos, const OUString& rId) override 4254 { 4255 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); 4256 set_id(pEntry, rId); 4257 } 4258 4259 virtual int get_selected_index() const override 4260 { 4261 assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen"); 4262 SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); 4263 if (!pEntry) 4264 return -1; 4265 return SvTreeList::GetRelPos(pEntry); 4266 } 4267 4268 virtual OUString get_selected_text() const override 4269 { 4270 assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen"); 4271 if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected()) 4272 return m_xTreeView->GetEntryText(pEntry); 4273 return OUString(); 4274 } 4275 4276 virtual OUString get_selected_id() const override 4277 { 4278 assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen"); 4279 if (SvTreeListEntry* pEntry = m_xTreeView->FirstSelected()) 4280 { 4281 if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData())) 4282 return *pStr; 4283 } 4284 return OUString(); 4285 } 4286 4287 virtual std::unique_ptr<weld::TreeIter> 4288 make_iterator(const weld::TreeIter* pOrig) const override 4289 { 4290 return std::unique_ptr<weld::TreeIter>( 4291 new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig))); 4292 } 4293 4294 virtual void copy_iterator(const weld::TreeIter& rSource, weld::TreeIter& rDest) const override 4295 { 4296 const SalInstanceTreeIter& rVclSource(static_cast<const SalInstanceTreeIter&>(rSource)); 4297 SalInstanceTreeIter& rVclDest(static_cast<SalInstanceTreeIter&>(rDest)); 4298 rVclDest.iter = rVclSource.iter; 4299 } 4300 4301 virtual bool get_selected(weld::TreeIter* pIter) const override 4302 { 4303 SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); 4304 auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); 4305 if (pVclIter) 4306 pVclIter->iter = pEntry; 4307 return pEntry != nullptr; 4308 } 4309 4310 virtual bool get_cursor(weld::TreeIter* pIter) const override 4311 { 4312 SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry(); 4313 auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); 4314 if (pVclIter) 4315 pVclIter->iter = pEntry; 4316 return pEntry != nullptr; 4317 } 4318 4319 virtual void set_cursor(const weld::TreeIter& rIter) override 4320 { 4321 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4322 disable_notify_events(); 4323 m_xTreeView->SetCurEntry(rVclIter.iter); 4324 enable_notify_events(); 4325 } 4326 4327 virtual bool get_iter_first(weld::TreeIter& rIter) const override 4328 { 4329 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4330 rVclIter.iter = m_xTreeView->GetEntry(0); 4331 return rVclIter.iter != nullptr; 4332 } 4333 4334 virtual bool iter_next_sibling(weld::TreeIter& rIter) const override 4335 { 4336 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4337 rVclIter.iter = rVclIter.iter->NextSibling(); 4338 return rVclIter.iter != nullptr; 4339 } 4340 4341 virtual bool iter_previous_sibling(weld::TreeIter& rIter) const override 4342 { 4343 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4344 rVclIter.iter = rVclIter.iter->PrevSibling(); 4345 return rVclIter.iter != nullptr; 4346 } 4347 4348 virtual bool iter_next(weld::TreeIter& rIter) const override 4349 { 4350 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4351 rVclIter.iter = m_xTreeView->Next(rVclIter.iter); 4352 if (rVclIter.iter && IsDummyEntry(rVclIter.iter)) 4353 return iter_next(rVclIter); 4354 return rVclIter.iter != nullptr; 4355 } 4356 4357 virtual bool iter_previous(weld::TreeIter& rIter) const override 4358 { 4359 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4360 rVclIter.iter = m_xTreeView->Prev(rVclIter.iter); 4361 if (rVclIter.iter && IsDummyEntry(rVclIter.iter)) 4362 return iter_previous(rVclIter); 4363 return rVclIter.iter != nullptr; 4364 } 4365 4366 virtual bool iter_next_visible(weld::TreeIter& rIter) const override 4367 { 4368 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4369 rVclIter.iter = m_xTreeView->NextVisible(rVclIter.iter); 4370 if (rVclIter.iter && IsDummyEntry(rVclIter.iter)) 4371 return iter_next_visible(rVclIter); 4372 return rVclIter.iter != nullptr; 4373 } 4374 4375 virtual bool iter_children(weld::TreeIter& rIter) const override 4376 { 4377 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4378 rVclIter.iter = m_xTreeView->FirstChild(rVclIter.iter); 4379 bool bRet = rVclIter.iter != nullptr; 4380 if (bRet) 4381 { 4382 //on-demand dummy entry doesn't count 4383 return !IsDummyEntry(rVclIter.iter); 4384 } 4385 return bRet; 4386 } 4387 4388 virtual bool iter_parent(weld::TreeIter& rIter) const override 4389 { 4390 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 4391 rVclIter.iter = m_xTreeView->GetParent(rVclIter.iter); 4392 return rVclIter.iter != nullptr; 4393 } 4394 4395 virtual void remove(const weld::TreeIter& rIter) override 4396 { 4397 disable_notify_events(); 4398 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4399 m_xTreeView->RemoveEntry(rVclIter.iter); 4400 enable_notify_events(); 4401 } 4402 4403 virtual void select(const weld::TreeIter& rIter) override 4404 { 4405 assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 4406 disable_notify_events(); 4407 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4408 m_xTreeView->Select(rVclIter.iter, true); 4409 enable_notify_events(); 4410 } 4411 4412 virtual void scroll_to_row(const weld::TreeIter& rIter) override 4413 { 4414 assert(m_xTreeView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 4415 disable_notify_events(); 4416 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4417 m_xTreeView->MakeVisible(rVclIter.iter); 4418 enable_notify_events(); 4419 } 4420 4421 virtual void unselect(const weld::TreeIter& rIter) override 4422 { 4423 assert(m_xTreeView->IsUpdateMode() && "don't unselect when frozen"); 4424 disable_notify_events(); 4425 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4426 m_xTreeView->Select(rVclIter.iter, false); 4427 enable_notify_events(); 4428 } 4429 4430 virtual int get_iter_depth(const weld::TreeIter& rIter) const override 4431 { 4432 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4433 return m_xTreeView->GetModel()->GetDepth(rVclIter.iter); 4434 } 4435 4436 virtual bool iter_has_child(const weld::TreeIter& rIter) const override 4437 { 4438 weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter); 4439 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter); 4440 SvTreeListEntry* restore(rVclIter.iter); 4441 bool ret = iter_children(rNonConstIter); 4442 rVclIter.iter = restore; 4443 return ret; 4444 } 4445 4446 virtual bool get_row_expanded(const weld::TreeIter& rIter) const override 4447 { 4448 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4449 return m_xTreeView->IsExpanded(rVclIter.iter); 4450 } 4451 4452 virtual bool get_children_on_demand(const weld::TreeIter& rIter) const override 4453 { 4454 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4455 if (m_aExpandingPlaceHolderParents.count(rVclIter.iter)) 4456 return true; 4457 return GetPlaceHolderChild(rVclIter.iter) != nullptr; 4458 } 4459 4460 virtual void set_children_on_demand(const weld::TreeIter& rIter, bool bChildrenOnDemand) override 4461 { 4462 disable_notify_events(); 4463 4464 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4465 4466 SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(rVclIter.iter); 4467 4468 if (bChildrenOnDemand && !pPlaceHolder) 4469 { 4470 pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", rVclIter.iter, false, 0, nullptr); 4471 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder); 4472 pViewData->SetSelectable(false); 4473 } 4474 else if (!bChildrenOnDemand && pPlaceHolder) 4475 m_xTreeView->RemoveEntry(pPlaceHolder); 4476 4477 enable_notify_events(); 4478 } 4479 4480 virtual void expand_row(const weld::TreeIter& rIter) override 4481 { 4482 assert(m_xTreeView->IsUpdateMode() && "don't expand when frozen"); 4483 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4484 if (!m_xTreeView->IsExpanded(rVclIter.iter) && signal_expanding(rIter)) 4485 m_xTreeView->Expand(rVclIter.iter); 4486 } 4487 4488 virtual void collapse_row(const weld::TreeIter& rIter) override 4489 { 4490 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4491 if (m_xTreeView->IsExpanded(rVclIter.iter) && signal_collapsing(rIter)) 4492 m_xTreeView->Collapse(rVclIter.iter); 4493 } 4494 4495 virtual OUString get_text(const weld::TreeIter& rIter, int col) const override 4496 { 4497 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4498 return get_text(rVclIter.iter, col); 4499 } 4500 4501 virtual void set_text(const weld::TreeIter& rIter, const OUString& rText, int col) override 4502 { 4503 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4504 set_text(rVclIter.iter, rText, col); 4505 } 4506 4507 virtual OUString get_id(const weld::TreeIter& rIter) const override 4508 { 4509 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4510 const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData()); 4511 if (pStr) 4512 return *pStr; 4513 return OUString(); 4514 } 4515 4516 virtual void set_id(const weld::TreeIter& rIter, const OUString& rId) override 4517 { 4518 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4519 set_id(rVclIter.iter, rId); 4520 } 4521 4522 virtual void enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, 4523 sal_uInt8 eDNDConstants) override 4524 { 4525 m_xTreeView->SetDragHelper(rHelper, eDNDConstants); 4526 } 4527 4528 virtual void set_selection_mode(SelectionMode eMode) override 4529 { 4530 m_xTreeView->SetSelectionMode(eMode); 4531 } 4532 4533 virtual void all_foreach(const std::function<bool(weld::TreeIter&)>& func) override 4534 { 4535 SalInstanceTreeIter aVclIter(m_xTreeView->First()); 4536 while (aVclIter.iter) 4537 { 4538 if (func(aVclIter)) 4539 return; 4540 iter_next(aVclIter); 4541 } 4542 } 4543 4544 virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override 4545 { 4546 SalInstanceTreeIter aVclIter(m_xTreeView->FirstSelected()); 4547 while (aVclIter.iter) 4548 { 4549 if (func(aVclIter)) 4550 return; 4551 aVclIter.iter = m_xTreeView->NextSelected(aVclIter.iter); 4552 } 4553 } 4554 4555 virtual void visible_foreach(const std::function<bool(weld::TreeIter&)>& func) override 4556 { 4557 SalInstanceTreeIter aVclIter(m_xTreeView->GetFirstEntryInView()); 4558 while (aVclIter.iter) 4559 { 4560 if (func(aVclIter)) 4561 return; 4562 aVclIter.iter = m_xTreeView->GetNextEntryInView(aVclIter.iter); 4563 } 4564 } 4565 4566 virtual void connect_visible_range_changed(const Link<weld::TreeView&, void>& rLink) override 4567 { 4568 weld::TreeView::connect_visible_range_changed(rLink); 4569 m_xTreeView->SetScrolledHdl(LINK(this, SalInstanceTreeView, VisibleRangeChangedHdl)); 4570 } 4571 4572 virtual void remove_selection() override 4573 { 4574 disable_notify_events(); 4575 SvTreeListEntry* pSelected = m_xTreeView->FirstSelected(); 4576 while (pSelected) 4577 { 4578 SvTreeListEntry* pNextSelected = m_xTreeView->NextSelected(pSelected); 4579 m_xTreeView->RemoveEntry(pSelected); 4580 pSelected = pNextSelected; 4581 } 4582 enable_notify_events(); 4583 } 4584 4585 virtual bool is_selected(const weld::TreeIter& rIter) const override 4586 { 4587 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4588 return m_xTreeView->IsSelected(rVclIter.iter); 4589 } 4590 4591 virtual int get_iter_index_in_parent(const weld::TreeIter& rIter) const override 4592 { 4593 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 4594 return SvTreeList::GetRelPos(rVclIter.iter); 4595 } 4596 4597 virtual int iter_compare(const weld::TreeIter& a, const weld::TreeIter& b) const override 4598 { 4599 const SalInstanceTreeIter& rVclIterA = static_cast<const SalInstanceTreeIter&>(a); 4600 const SalInstanceTreeIter& rVclIterB = static_cast<const SalInstanceTreeIter&>(b); 4601 const SvTreeList* pModel = m_xTreeView->GetModel(); 4602 auto nAbsPosA = pModel->GetAbsPos(rVclIterA.iter); 4603 auto nAbsPosB = pModel->GetAbsPos(rVclIterB.iter); 4604 if (nAbsPosA < nAbsPosB) 4605 return -1; 4606 if (nAbsPosA > nAbsPosB) 4607 return 1; 4608 return 0; 4609 } 4610 4611 virtual void move_subtree(weld::TreeIter& rNode, const weld::TreeIter* pNewParent, 4612 int nIndexInNewParent) override 4613 { 4614 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNode); 4615 const SalInstanceTreeIter* pVclParentIter 4616 = static_cast<const SalInstanceTreeIter*>(pNewParent); 4617 m_xTreeView->GetModel()->Move( 4618 rVclIter.iter, pVclParentIter ? pVclParentIter->iter : nullptr, nIndexInNewParent); 4619 } 4620 4621 virtual int count_selected_rows() const override { return m_xTreeView->GetSelectionCount(); } 4622 4623 virtual int get_height_rows(int nRows) const override 4624 { 4625 return m_xTreeView->GetEntryHeight() * nRows; 4626 } 4627 4628 virtual void make_sorted() override 4629 { 4630 assert(m_xTreeView->IsUpdateMode() && "don't sort when frozen"); 4631 m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT); 4632 m_xTreeView->GetModel()->SetCompareHdl(LINK(this, SalInstanceTreeView, CompareHdl)); 4633 set_sort_order(true); 4634 } 4635 4636 virtual void set_sort_func( 4637 const std::function<int(const weld::TreeIter&, const weld::TreeIter&)>& func) override 4638 { 4639 weld::TreeView::set_sort_func(func); 4640 SvTreeList* pListModel = m_xTreeView->GetModel(); 4641 pListModel->Resort(); 4642 } 4643 4644 virtual void make_unsorted() override 4645 { 4646 m_xTreeView->SetStyle(m_xTreeView->GetStyle() & ~WB_SORT); 4647 } 4648 4649 virtual void set_sort_order(bool bAscending) override 4650 { 4651 SvTreeList* pListModel = m_xTreeView->GetModel(); 4652 pListModel->SetSortMode(bAscending ? SortAscending : SortDescending); 4653 pListModel->Resort(); 4654 } 4655 4656 virtual bool get_sort_order() const override 4657 { 4658 return m_xTreeView->GetModel()->GetSortMode() == SortAscending; 4659 } 4660 4661 virtual void set_sort_indicator(TriState eState, int col) override 4662 { 4663 assert(col >= 0 && "cannot sort on expander column"); 4664 4665 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 4666 HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr; 4667 if (!pHeaderBar) 4668 return; 4669 4670 sal_uInt16 nTextId = pHeaderBar->GetItemId(col); 4671 HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId); 4672 nBits &= ~HeaderBarItemBits::UPARROW; 4673 nBits &= ~HeaderBarItemBits::DOWNARROW; 4674 if (eState != TRISTATE_INDET) 4675 { 4676 if (eState == TRISTATE_TRUE) 4677 nBits |= HeaderBarItemBits::DOWNARROW; 4678 else 4679 nBits |= HeaderBarItemBits::UPARROW; 4680 } 4681 pHeaderBar->SetItemBits(nTextId, nBits); 4682 } 4683 4684 virtual TriState get_sort_indicator(int col) const override 4685 { 4686 assert(col >= 0 && "cannot sort on expander column"); 4687 4688 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 4689 if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) 4690 { 4691 sal_uInt16 nTextId = pHeaderBar->GetItemId(col); 4692 HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId); 4693 if (nBits & HeaderBarItemBits::DOWNARROW) 4694 return TRISTATE_TRUE; 4695 if (nBits & HeaderBarItemBits::UPARROW) 4696 return TRISTATE_FALSE; 4697 } 4698 4699 return TRISTATE_INDET; 4700 } 4701 4702 virtual int get_sort_column() const override { return m_nSortColumn; } 4703 4704 virtual void set_sort_column(int nColumn) override 4705 { 4706 if (nColumn == -1) 4707 { 4708 make_unsorted(); 4709 m_nSortColumn = -1; 4710 return; 4711 } 4712 4713 if (nColumn != m_nSortColumn) 4714 { 4715 m_nSortColumn = nColumn; 4716 m_xTreeView->GetModel()->Resort(); 4717 } 4718 } 4719 4720 SvTabListBox& getTreeView() { return *m_xTreeView; } 4721 4722 virtual bool get_dest_row_at_pos(const Point& rPos, weld::TreeIter* pResult, bool bDnDMode) override 4723 { 4724 LclTabListBox* pTreeView = !bDnDMode ? dynamic_cast<LclTabListBox*>(m_xTreeView.get()) : nullptr; 4725 SvTreeListEntry* pTarget = pTreeView ? pTreeView->GetTargetAtPoint(rPos, false) : m_xTreeView->GetDropTarget(rPos); 4726 4727 if (pTarget && pResult) 4728 { 4729 SalInstanceTreeIter& rSalIter = static_cast<SalInstanceTreeIter&>(*pResult); 4730 rSalIter.iter = pTarget; 4731 } 4732 4733 return pTarget != nullptr; 4734 } 4735 4736 virtual void unset_drag_dest_row() override 4737 { 4738 m_xTreeView->UnsetDropTarget(); 4739 } 4740 4741 virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const override 4742 { 4743 return m_xTreeView->GetBoundingRect(static_cast<const SalInstanceTreeIter&>(rIter).iter); 4744 } 4745 4746 virtual TreeView* get_drag_source() const override { return g_DragSource; } 4747 4748 virtual int vadjustment_get_value() const override 4749 { 4750 int nValue = -1; 4751 const SvTreeListEntry* pEntry = m_xTreeView->GetFirstEntryInView(); 4752 if (pEntry) 4753 nValue = m_xTreeView->GetAbsPos(pEntry); 4754 return nValue; 4755 } 4756 4757 virtual void vadjustment_set_value(int nValue) override 4758 { 4759 if (nValue == -1) 4760 return; 4761 bool bUpdate = m_xTreeView->IsUpdateMode(); 4762 if (bUpdate) 4763 m_xTreeView->SetUpdateMode(false); 4764 m_xTreeView->ScrollToAbsPos(nValue); 4765 if (bUpdate) 4766 m_xTreeView->SetUpdateMode(true); 4767 } 4768 4769 void set_show_expanders(bool bShow) override 4770 { 4771 m_xTreeView->set_property("show-expanders", OUString::boolean(bShow)); 4772 } 4773 4774 virtual ~SalInstanceTreeView() override 4775 { 4776 LclHeaderTabListBox* pHeaderBox = dynamic_cast<LclHeaderTabListBox*>(m_xTreeView.get()); 4777 if (pHeaderBox) 4778 { 4779 if (HeaderBar* pHeaderBar = pHeaderBox->GetHeaderBar()) 4780 { 4781 pHeaderBar->SetSelectHdl(Link<HeaderBar*, void>()); 4782 pHeaderBar->SetEndDragHdl(Link<HeaderBar*, void>()); 4783 } 4784 } 4785 else 4786 { 4787 static_cast<LclTabListBox&>(*m_xTreeView).SetEndDragHdl(Link<SvTreeListBox*, void>()); 4788 static_cast<LclTabListBox&>(*m_xTreeView).SetStartDragHdl(Link<SvTreeListBox*, bool>()); 4789 static_cast<LclTabListBox&>(*m_xTreeView) 4790 .SetModelChangedHdl(Link<SvTreeListBox*, void>()); 4791 } 4792 m_xTreeView->SetPopupMenuHdl(Link<const CommandEvent&, bool>()); 4793 m_xTreeView->SetExpandingHdl(Link<SvTreeListBox*, bool>()); 4794 m_xTreeView->SetDoubleClickHdl(Link<SvTreeListBox*, bool>()); 4795 m_xTreeView->SetSelectHdl(Link<SvTreeListBox*, void>()); 4796 m_xTreeView->SetDeselectHdl(Link<SvTreeListBox*, void>()); 4797 m_xTreeView->SetScrolledHdl(Link<SvTreeListBox*, void>()); 4798 m_xTreeView->SetTooltipHdl(Link<const HelpEvent&, bool>()); 4799 m_xTreeView->SetCustomRenderHdl(Link<svtree_render_args, void>()); 4800 m_xTreeView->SetCustomMeasureHdl(Link<svtree_measure_args, Size>()); 4801 } 4802 }; 4803 4804 IMPL_LINK(SalInstanceTreeView, TooltipHdl, const HelpEvent&, rHEvt, bool) 4805 { 4806 if (notify_events_disabled()) 4807 return false; 4808 Point aPos(m_xTreeView->ScreenToOutputPixel(rHEvt.GetMousePosPixel())); 4809 SvTreeListEntry* pEntry = m_xTreeView->GetEntry(aPos); 4810 if (pEntry) 4811 { 4812 SalInstanceTreeIter aIter(pEntry); 4813 OUString aTooltip = signal_query_tooltip(aIter); 4814 if (aTooltip.isEmpty()) 4815 return false; 4816 Size aSize(m_xTreeView->GetOutputSizePixel().Width(), m_xTreeView->GetEntryHeight()); 4817 tools::Rectangle aScreenRect( 4818 m_xTreeView->OutputToScreenPixel(m_xTreeView->GetEntryPosition(pEntry)), aSize); 4819 Help::ShowQuickHelp(m_xTreeView, aScreenRect, aTooltip); 4820 } 4821 return true; 4822 } 4823 4824 IMPL_LINK(SalInstanceTreeView, CustomRenderHdl, svtree_render_args, payload, void) 4825 { 4826 vcl::RenderContext& rRenderDevice = std::get<0>(payload); 4827 const tools::Rectangle& rRect = std::get<1>(payload); 4828 const SvTreeListEntry& rEntry = std::get<2>(payload); 4829 const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData()); 4830 if (!pId) 4831 return; 4832 signal_custom_render(rRenderDevice, rRect, m_xTreeView->IsSelected(&rEntry), *pId); 4833 } 4834 4835 IMPL_LINK(SalInstanceTreeView, CustomMeasureHdl, svtree_measure_args, payload, Size) 4836 { 4837 vcl::RenderContext& rRenderDevice = payload.first; 4838 const SvTreeListEntry& rEntry = payload.second; 4839 const OUString* pId = static_cast<const OUString*>(rEntry.GetUserData()); 4840 if (!pId) 4841 return Size(); 4842 return signal_custom_get_size(rRenderDevice, *pId); 4843 } 4844 4845 IMPL_LINK(SalInstanceTreeView, CompareHdl, const SvSortData&, rSortData, sal_Int32) 4846 { 4847 const SvTreeListEntry* pLHS = rSortData.pLeft; 4848 const SvTreeListEntry* pRHS = rSortData.pRight; 4849 assert(pLHS && pRHS); 4850 4851 if (m_aCustomSort) 4852 return m_aCustomSort(SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pLHS)), 4853 SalInstanceTreeIter(const_cast<SvTreeListEntry*>(pRHS))); 4854 4855 const SvLBoxString* pLeftTextItem; 4856 const SvLBoxString* pRightTextItem; 4857 4858 if (m_nSortColumn != -1) 4859 { 4860 size_t col = to_internal_model(m_nSortColumn); 4861 4862 if (col < pLHS->ItemCount()) 4863 { 4864 const SvLBoxString& rLeftTextItem 4865 = static_cast<const SvLBoxString&>(pLHS->GetItem(col)); 4866 pLeftTextItem = &rLeftTextItem; 4867 } 4868 else 4869 pLeftTextItem = nullptr; 4870 if (col < pRHS->ItemCount()) 4871 { 4872 const SvLBoxString& rRightTextItem 4873 = static_cast<const SvLBoxString&>(pRHS->GetItem(col)); 4874 pRightTextItem = &rRightTextItem; 4875 } 4876 else 4877 pRightTextItem = nullptr; 4878 } 4879 else 4880 { 4881 pLeftTextItem 4882 = static_cast<const SvLBoxString*>(pLHS->GetFirstItem(SvLBoxItemType::String)); 4883 pRightTextItem 4884 = static_cast<const SvLBoxString*>(pRHS->GetFirstItem(SvLBoxItemType::String)); 4885 } 4886 4887 return m_xTreeView->DefaultCompare(pLeftTextItem, pRightTextItem); 4888 } 4889 4890 IMPL_LINK_NOARG(SalInstanceTreeView, VisibleRangeChangedHdl, SvTreeListBox*, void) 4891 { 4892 if (notify_events_disabled()) 4893 return; 4894 signal_visible_range_changed(); 4895 } 4896 4897 IMPL_LINK_NOARG(SalInstanceTreeView, ModelChangedHdl, SvTreeListBox*, void) 4898 { 4899 if (notify_events_disabled()) 4900 return; 4901 signal_model_changed(); 4902 } 4903 4904 IMPL_LINK_NOARG(SalInstanceTreeView, StartDragHdl, SvTreeListBox*, bool) 4905 { 4906 bool bUnsetDragIcon(false); // ignored for vcl 4907 if (m_aDragBeginHdl.Call(bUnsetDragIcon)) 4908 return true; 4909 g_DragSource = this; 4910 return false; 4911 } 4912 4913 IMPL_STATIC_LINK_NOARG(SalInstanceTreeView, FinishDragHdl, SvTreeListBox*, void) 4914 { 4915 g_DragSource = nullptr; 4916 } 4917 4918 IMPL_LINK(SalInstanceTreeView, ToggleHdl, SvLBoxButtonData*, pData, void) 4919 { 4920 SvTreeListEntry* pEntry = pData->GetActEntry(); 4921 SvLBoxButton* pBox = pData->GetActBox(); 4922 4923 // tdf#122874 Select the row, calling SelectHdl, before handling 4924 // the toggle 4925 if (!m_xTreeView->IsSelected(pEntry)) 4926 { 4927 m_xTreeView->SelectAll(false); 4928 m_xTreeView->Select(pEntry, true); 4929 } 4930 4931 // additionally set the cursor into the row the toggled element is in 4932 m_xTreeView->pImpl->m_pCursor = pEntry; 4933 4934 for (int i = 0, nCount = pEntry->ItemCount(); i < nCount; ++i) 4935 { 4936 SvLBoxItem& rItem = pEntry->GetItem(i); 4937 if (&rItem == pBox) 4938 { 4939 int nCol = to_external_model(i); 4940 signal_toggled(iter_col(SalInstanceTreeIter(pEntry), nCol)); 4941 break; 4942 } 4943 } 4944 } 4945 4946 IMPL_LINK_NOARG(SalInstanceTreeView, SelectHdl, SvTreeListBox*, void) 4947 { 4948 if (notify_events_disabled()) 4949 return; 4950 signal_changed(); 4951 } 4952 4953 IMPL_LINK_NOARG(SalInstanceTreeView, DeSelectHdl, SvTreeListBox*, void) 4954 { 4955 if (notify_events_disabled()) 4956 return; 4957 if (m_xTreeView->GetSelectionMode() == SelectionMode::Single && !m_xTreeView->GetHoverSelection()) 4958 return; 4959 signal_changed(); 4960 } 4961 4962 IMPL_LINK_NOARG(SalInstanceTreeView, DoubleClickHdl, SvTreeListBox*, bool) 4963 { 4964 if (notify_events_disabled()) 4965 return false; 4966 return !signal_row_activated(); 4967 } 4968 4969 IMPL_LINK(SalInstanceTreeView, EndDragHdl, HeaderBar*, pHeaderBar, void) 4970 { 4971 std::vector<long> aTabPositions; 4972 aTabPositions.push_back(0); 4973 for (int i = 0; i < pHeaderBar->GetItemCount() - 1; ++i) 4974 aTabPositions.push_back(aTabPositions[i] 4975 + pHeaderBar->GetItemSize(pHeaderBar->GetItemId(i))); 4976 m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel); 4977 } 4978 4979 IMPL_LINK(SalInstanceTreeView, HeaderBarClickedHdl, HeaderBar*, pHeaderBar, void) 4980 { 4981 sal_uInt16 nId = pHeaderBar->GetCurItemId(); 4982 if (!(pHeaderBar->GetItemBits(nId) & HeaderBarItemBits::CLICKABLE)) 4983 return; 4984 signal_column_clicked(pHeaderBar->GetItemPos(nId)); 4985 } 4986 4987 IMPL_LINK_NOARG(SalInstanceTreeView, ExpandingHdl, SvTreeListBox*, bool) 4988 { 4989 SvTreeListEntry* pEntry = m_xTreeView->GetHdlEntry(); 4990 SalInstanceTreeIter aIter(pEntry); 4991 4992 if (m_xTreeView->IsExpanded(pEntry)) 4993 { 4994 //collapsing; 4995 return signal_collapsing(aIter); 4996 } 4997 4998 // expanding 4999 5000 // if there's a preexisting placeholder child, required to make this 5001 // potentially expandable in the first place, now we remove it 5002 SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(pEntry); 5003 if (pPlaceHolder) 5004 { 5005 m_aExpandingPlaceHolderParents.insert(pEntry); 5006 m_xTreeView->RemoveEntry(pPlaceHolder); 5007 } 5008 5009 bool bRet = signal_expanding(aIter); 5010 5011 if (pPlaceHolder) 5012 { 5013 //expand disallowed, restore placeholder 5014 if (!bRet) 5015 { 5016 pPlaceHolder = m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr); 5017 SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pPlaceHolder); 5018 pViewData->SetSelectable(false); 5019 } 5020 m_aExpandingPlaceHolderParents.erase(pEntry); 5021 } 5022 5023 return bRet; 5024 } 5025 5026 IMPL_LINK(SalInstanceTreeView, PopupMenuHdl, const CommandEvent&, rEvent, bool) 5027 { 5028 return m_aPopupMenuHdl.Call(rEvent); 5029 } 5030 5031 IMPL_LINK(SalInstanceTreeView, EditingEntryHdl, SvTreeListEntry*, pEntry, bool) 5032 { 5033 return signal_editing_started(SalInstanceTreeIter(pEntry)); 5034 } 5035 5036 IMPL_LINK(SalInstanceTreeView, EditedEntryHdl, IterString, rIterString, bool) 5037 { 5038 return signal_editing_done(iter_string( 5039 SalInstanceTreeIter(rIterString.first), rIterString.second)); 5040 } 5041 5042 class SalInstanceIconView : public SalInstanceContainer, public virtual weld::IconView 5043 { 5044 private: 5045 // owner for UserData 5046 std::vector<std::unique_ptr<OUString>> m_aUserData; 5047 VclPtr<::IconView> m_xIconView; 5048 5049 DECL_LINK(SelectHdl, SvTreeListBox*, void); 5050 DECL_LINK(DeSelectHdl, SvTreeListBox*, void); 5051 DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool); 5052 5053 public: 5054 SalInstanceIconView(::IconView* pIconView, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 5055 : SalInstanceContainer(pIconView, pBuilder, bTakeOwnership) 5056 , m_xIconView(pIconView) 5057 { 5058 m_xIconView->SetSelectHdl(LINK(this, SalInstanceIconView, SelectHdl)); 5059 m_xIconView->SetDeselectHdl(LINK(this, SalInstanceIconView, DeSelectHdl)); 5060 m_xIconView->SetDoubleClickHdl(LINK(this, SalInstanceIconView, DoubleClickHdl)); 5061 } 5062 5063 virtual void freeze() override 5064 { 5065 SalInstanceWidget::freeze(); 5066 m_xIconView->SetUpdateMode(false); 5067 } 5068 5069 virtual void thaw() override 5070 { 5071 m_xIconView->SetUpdateMode(true); 5072 SalInstanceWidget::thaw(); 5073 } 5074 5075 virtual void insert(int pos, const OUString* pStr, const OUString* pId, 5076 const OUString* pIconName, weld::TreeIter* pRet) override 5077 { 5078 disable_notify_events(); 5079 auto nInsertPos = pos == -1 ? TREELIST_APPEND : pos; 5080 void* pUserData; 5081 if (pId) 5082 { 5083 m_aUserData.emplace_back(std::make_unique<OUString>(*pId)); 5084 pUserData = m_aUserData.back().get(); 5085 } 5086 else 5087 pUserData = nullptr; 5088 5089 SvTreeListEntry* pEntry = new SvTreeListEntry; 5090 if (pIconName) 5091 { 5092 Image aImage(createImage(*pIconName)); 5093 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aImage, aImage, false)); 5094 } 5095 else 5096 { 5097 Image aDummy; 5098 pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false)); 5099 } 5100 if (pStr) 5101 pEntry->AddItem(std::make_unique<SvLBoxString>(*pStr)); 5102 pEntry->SetUserData(pUserData); 5103 m_xIconView->Insert(pEntry, nullptr, nInsertPos); 5104 5105 if (pRet) 5106 { 5107 SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet); 5108 pVclRetIter->iter = pEntry; 5109 } 5110 5111 enable_notify_events(); 5112 } 5113 5114 virtual OUString get_selected_id() const override 5115 { 5116 assert(m_xIconView->IsUpdateMode() && "don't request selection when frozen"); 5117 if (SvTreeListEntry* pEntry = m_xIconView->FirstSelected()) 5118 { 5119 if (const OUString* pStr = static_cast<const OUString*>(pEntry->GetUserData())) 5120 return *pStr; 5121 } 5122 return OUString(); 5123 } 5124 5125 virtual OUString get_selected_text() const override 5126 { 5127 assert(m_xIconView->IsUpdateMode() && "don't request selection when frozen"); 5128 if (SvTreeListEntry* pEntry = m_xIconView->FirstSelected()) 5129 return m_xIconView->GetEntryText(pEntry); 5130 return OUString(); 5131 } 5132 5133 virtual int count_selected_items() const override { return m_xIconView->GetSelectionCount(); } 5134 5135 virtual void select(int pos) override 5136 { 5137 assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 5138 disable_notify_events(); 5139 if (pos == -1 || (pos == 0 && n_children() == 0)) 5140 m_xIconView->SelectAll(false); 5141 else 5142 { 5143 SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos); 5144 m_xIconView->Select(pEntry, true); 5145 m_xIconView->MakeVisible(pEntry); 5146 } 5147 enable_notify_events(); 5148 } 5149 5150 virtual void unselect(int pos) override 5151 { 5152 assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 5153 disable_notify_events(); 5154 if (pos == -1) 5155 m_xIconView->SelectAll(true); 5156 else 5157 { 5158 SvTreeListEntry* pEntry = m_xIconView->GetEntry(nullptr, pos); 5159 m_xIconView->Select(pEntry, false); 5160 } 5161 enable_notify_events(); 5162 } 5163 5164 virtual int n_children() const override 5165 { 5166 return m_xIconView->GetModel()->GetChildList(nullptr).size(); 5167 } 5168 5169 virtual std::unique_ptr<weld::TreeIter> 5170 make_iterator(const weld::TreeIter* pOrig) const override 5171 { 5172 return std::unique_ptr<weld::TreeIter>( 5173 new SalInstanceTreeIter(static_cast<const SalInstanceTreeIter*>(pOrig))); 5174 } 5175 5176 virtual bool get_selected(weld::TreeIter* pIter) const override 5177 { 5178 SvTreeListEntry* pEntry = m_xIconView->FirstSelected(); 5179 auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); 5180 if (pVclIter) 5181 pVclIter->iter = pEntry; 5182 return pEntry != nullptr; 5183 } 5184 5185 virtual bool get_cursor(weld::TreeIter* pIter) const override 5186 { 5187 SvTreeListEntry* pEntry = m_xIconView->GetCurEntry(); 5188 auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); 5189 if (pVclIter) 5190 pVclIter->iter = pEntry; 5191 return pEntry != nullptr; 5192 } 5193 5194 virtual void set_cursor(const weld::TreeIter& rIter) override 5195 { 5196 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 5197 disable_notify_events(); 5198 m_xIconView->SetCurEntry(rVclIter.iter); 5199 enable_notify_events(); 5200 } 5201 5202 virtual bool get_iter_first(weld::TreeIter& rIter) const override 5203 { 5204 SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); 5205 rVclIter.iter = m_xIconView->GetEntry(0); 5206 return rVclIter.iter != nullptr; 5207 } 5208 5209 virtual void scroll_to_item(const weld::TreeIter& rIter) override 5210 { 5211 assert(m_xIconView->IsUpdateMode() && "don't select when frozen, select after thaw. Note selection doesn't survive a freeze"); 5212 disable_notify_events(); 5213 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 5214 m_xIconView->MakeVisible(rVclIter.iter); 5215 enable_notify_events(); 5216 } 5217 5218 virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override 5219 { 5220 SalInstanceTreeIter aVclIter(m_xIconView->FirstSelected()); 5221 while (aVclIter.iter) 5222 { 5223 if (func(aVclIter)) 5224 return; 5225 aVclIter.iter = m_xIconView->NextSelected(aVclIter.iter); 5226 } 5227 } 5228 5229 virtual OUString get_id(const weld::TreeIter& rIter) const override 5230 { 5231 const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); 5232 const OUString* pStr = static_cast<const OUString*>(rVclIter.iter->GetUserData()); 5233 if (pStr) 5234 return *pStr; 5235 return OUString(); 5236 } 5237 5238 virtual void clear() override 5239 { 5240 disable_notify_events(); 5241 m_xIconView->Clear(); 5242 m_aUserData.clear(); 5243 enable_notify_events(); 5244 } 5245 5246 virtual ~SalInstanceIconView() override 5247 { 5248 m_xIconView->SetDoubleClickHdl(Link<SvTreeListBox*, bool>()); 5249 m_xIconView->SetSelectHdl(Link<SvTreeListBox*, void>()); 5250 m_xIconView->SetDeselectHdl(Link<SvTreeListBox*, void>()); 5251 } 5252 }; 5253 5254 IMPL_LINK_NOARG(SalInstanceIconView, SelectHdl, SvTreeListBox*, void) 5255 { 5256 if (notify_events_disabled()) 5257 return; 5258 signal_selection_changed(); 5259 } 5260 5261 IMPL_LINK_NOARG(SalInstanceIconView, DeSelectHdl, SvTreeListBox*, void) 5262 { 5263 if (notify_events_disabled()) 5264 return; 5265 if (m_xIconView->GetSelectionMode() == SelectionMode::Single) 5266 return; 5267 signal_selection_changed(); 5268 } 5269 5270 IMPL_LINK_NOARG(SalInstanceIconView, DoubleClickHdl, SvTreeListBox*, bool) 5271 { 5272 if (notify_events_disabled()) 5273 return false; 5274 return !signal_item_activated(); 5275 } 5276 5277 double SalInstanceSpinButton::toField(int nValue) const 5278 { 5279 return static_cast<double>(nValue) / Power10(get_digits()); 5280 } 5281 5282 int SalInstanceSpinButton::fromField(double fValue) const 5283 { 5284 return FRound(fValue * Power10(get_digits())); 5285 } 5286 5287 SalInstanceSpinButton::SalInstanceSpinButton(FormattedField* pButton, SalInstanceBuilder* pBuilder, 5288 bool bTakeOwnership) 5289 : SalInstanceEntry(pButton, pBuilder, bTakeOwnership) 5290 , m_xButton(pButton) 5291 , m_rFormatter(m_xButton->GetFormatter()) 5292 { 5293 m_rFormatter.SetThousandsSep(false); //off by default, MetricSpinButton enables it 5294 m_xButton->SetUpHdl(LINK(this, SalInstanceSpinButton, UpDownHdl)); 5295 m_xButton->SetDownHdl(LINK(this, SalInstanceSpinButton, UpDownHdl)); 5296 m_xButton->SetLoseFocusHdl(LINK(this, SalInstanceSpinButton, LoseFocusHdl)); 5297 m_rFormatter.SetOutputHdl(LINK(this, SalInstanceSpinButton, OutputHdl)); 5298 m_rFormatter.SetInputHdl(LINK(this, SalInstanceSpinButton, InputHdl)); 5299 if (Edit* pEdit = m_xButton->GetSubEdit()) 5300 pEdit->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl)); 5301 else 5302 m_xButton->SetActivateHdl(LINK(this, SalInstanceSpinButton, ActivateHdl)); 5303 } 5304 5305 int SalInstanceSpinButton::get_value() const 5306 { 5307 return fromField(m_rFormatter.GetValue()); 5308 } 5309 5310 void SalInstanceSpinButton::set_value(int value) 5311 { 5312 m_rFormatter.SetValue(toField(value)); 5313 } 5314 5315 void SalInstanceSpinButton::set_range(int min, int max) 5316 { 5317 m_rFormatter.SetMinValue(toField(min)); 5318 m_rFormatter.SetMaxValue(toField(max)); 5319 } 5320 5321 void SalInstanceSpinButton::get_range(int& min, int& max) const 5322 { 5323 min = fromField(m_rFormatter.GetMinValue()); 5324 max = fromField(m_rFormatter.GetMaxValue()); 5325 } 5326 5327 void SalInstanceSpinButton::set_increments(int step, int /*page*/) 5328 { 5329 m_rFormatter.SetSpinSize(toField(step)); 5330 } 5331 5332 void SalInstanceSpinButton::get_increments(int& step, int& page) const 5333 { 5334 step = fromField(m_rFormatter.GetSpinSize()); 5335 page = fromField(m_rFormatter.GetSpinSize()); 5336 } 5337 5338 void SalInstanceSpinButton::set_digits(unsigned int digits) 5339 { 5340 m_rFormatter.SetDecimalDigits(digits); 5341 } 5342 5343 // SpinButton may be comprised of multiple subwidgets, consider the lot as 5344 // one thing for focus 5345 bool SalInstanceSpinButton::has_focus() const 5346 { 5347 return m_xWidget->HasChildPathFocus(); 5348 } 5349 5350 //off by default for direct SpinButtons, MetricSpinButton enables it 5351 void SalInstanceSpinButton::SetUseThousandSep() 5352 { 5353 m_rFormatter.SetThousandsSep(true); 5354 } 5355 5356 unsigned int SalInstanceSpinButton::get_digits() const 5357 { 5358 return m_rFormatter.GetDecimalDigits(); 5359 } 5360 5361 SalInstanceSpinButton::~SalInstanceSpinButton() 5362 { 5363 if (Edit* pEdit = m_xButton->GetSubEdit()) 5364 pEdit->SetActivateHdl(Link<Edit&, bool>()); 5365 else 5366 m_xButton->SetActivateHdl(Link<Edit&, bool>()); 5367 m_rFormatter.SetInputHdl(Link<sal_Int64*, TriState>()); 5368 m_rFormatter.SetOutputHdl(Link<LinkParamNone*, bool>()); 5369 m_xButton->SetLoseFocusHdl(Link<Control&, void>()); 5370 m_xButton->SetDownHdl(Link<SpinField&, void>()); 5371 m_xButton->SetUpHdl(Link<SpinField&, void>()); 5372 } 5373 5374 IMPL_LINK_NOARG(SalInstanceSpinButton, ActivateHdl, Edit&, bool) 5375 { 5376 // tdf#122348 return pressed to end dialog 5377 signal_value_changed(); 5378 return m_aActivateHdl.Call(*this); 5379 } 5380 5381 IMPL_LINK_NOARG(SalInstanceSpinButton, UpDownHdl, SpinField&, void) { signal_value_changed(); } 5382 5383 IMPL_LINK_NOARG(SalInstanceSpinButton, LoseFocusHdl, Control&, void) { signal_value_changed(); } 5384 5385 IMPL_LINK_NOARG(SalInstanceSpinButton, OutputHdl, LinkParamNone*, bool) { return signal_output(); } 5386 5387 IMPL_LINK(SalInstanceSpinButton, InputHdl, sal_Int64*, pResult, TriState) 5388 { 5389 int nResult; 5390 TriState eRet = signal_input(&nResult); 5391 if (eRet == TRISTATE_TRUE) 5392 *pResult = nResult; 5393 return eRet; 5394 } 5395 5396 namespace 5397 { 5398 class SalInstanceFormattedSpinButton : public SalInstanceEntry, 5399 public virtual weld::FormattedSpinButton 5400 { 5401 private: 5402 VclPtr<FormattedField> m_xButton; 5403 weld::EntryFormatter* m_pFormatter; 5404 5405 public: 5406 SalInstanceFormattedSpinButton(FormattedField* pButton, SalInstanceBuilder* pBuilder, 5407 bool bTakeOwnership) 5408 : SalInstanceEntry(pButton, pBuilder, bTakeOwnership) 5409 , m_xButton(pButton) 5410 , m_pFormatter(nullptr) 5411 { 5412 } 5413 5414 virtual void set_text(const OUString& rText) override 5415 { 5416 disable_notify_events(); 5417 m_xButton->SpinField::SetText(rText); 5418 enable_notify_events(); 5419 } 5420 5421 virtual void connect_changed(const Link<weld::Entry&, void>& rLink) override 5422 { 5423 if (!m_pFormatter) // once a formatter is set, it takes over "changed" 5424 { 5425 SalInstanceEntry::connect_changed(rLink); 5426 return; 5427 } 5428 m_pFormatter->connect_changed(rLink); 5429 } 5430 5431 virtual void connect_focus_out(const Link<weld::Widget&, void>& rLink) override 5432 { 5433 if (!m_pFormatter) // once a formatter is set, it takes over "focus-out" 5434 { 5435 SalInstanceEntry::connect_focus_out(rLink); 5436 return; 5437 } 5438 m_pFormatter->connect_focus_out(rLink); 5439 } 5440 5441 virtual void SetFormatter(weld::EntryFormatter* pFormatter) override 5442 { 5443 m_pFormatter = pFormatter; 5444 m_xButton->SetFormatter(pFormatter); 5445 } 5446 5447 virtual void sync_value_from_formatter() override 5448 { 5449 // no-op for gen 5450 } 5451 5452 virtual void sync_range_from_formatter() override 5453 { 5454 // no-op for gen 5455 } 5456 5457 virtual void sync_increments_from_formatter() override 5458 { 5459 // no-op for gen 5460 } 5461 5462 virtual Formatter& GetFormatter() override 5463 { 5464 return m_xButton->GetFormatter(); 5465 } 5466 }; 5467 5468 } 5469 5470 SalInstanceLabel::SalInstanceLabel(Control* pLabel, SalInstanceBuilder* pBuilder, 5471 bool bTakeOwnership) 5472 : SalInstanceWidget(pLabel, pBuilder, bTakeOwnership) 5473 , m_xLabel(pLabel) 5474 { 5475 } 5476 5477 void SalInstanceLabel::set_label(const OUString& rText) { m_xLabel->SetText(rText); } 5478 5479 OUString SalInstanceLabel::get_label() const { return m_xLabel->GetText(); } 5480 5481 void SalInstanceLabel::set_mnemonic_widget(Widget* pTarget) 5482 { 5483 FixedText* pLabel = dynamic_cast<FixedText*>(m_xLabel.get()); 5484 assert(pLabel && "can't use set_mnemonic_widget on SelectableFixedText"); 5485 SalInstanceWidget* pTargetWidget = dynamic_cast<SalInstanceWidget*>(pTarget); 5486 pLabel->set_mnemonic_widget(pTargetWidget ? pTargetWidget->getWidget() : nullptr); 5487 } 5488 5489 void SalInstanceLabel::set_label_type(weld::LabelType eType) 5490 { 5491 switch (eType) 5492 { 5493 case weld::LabelType::Normal: 5494 m_xLabel->SetControlForeground(); 5495 m_xLabel->SetControlBackground(); 5496 break; 5497 case weld::LabelType::Warning: 5498 m_xLabel->SetControlForeground(); 5499 m_xLabel->SetControlBackground(COL_YELLOW); 5500 break; 5501 case weld::LabelType::Error: 5502 m_xLabel->SetControlForeground(); 5503 m_xLabel->SetControlBackground( 5504 m_xLabel->GetSettings().GetStyleSettings().GetHighlightColor()); 5505 break; 5506 case weld::LabelType::Title: 5507 m_xLabel->SetControlForeground( 5508 m_xLabel->GetSettings().GetStyleSettings().GetLightColor()); 5509 m_xLabel->SetControlBackground(); 5510 break; 5511 } 5512 } 5513 5514 void SalInstanceLabel::set_font(const vcl::Font& rFont) 5515 { 5516 m_xLabel->SetPointFont(*m_xLabel, rFont); 5517 m_xLabel->Invalidate(); 5518 } 5519 5520 std::unique_ptr<weld::Label> SalInstanceFrame::weld_label_widget() const 5521 { 5522 FixedText* pLabel = dynamic_cast<FixedText*>(m_xFrame->get_label_widget()); 5523 if (!pLabel) 5524 return nullptr; 5525 return std::make_unique<SalInstanceLabel>(pLabel, m_pBuilder, false); 5526 } 5527 5528 SalInstanceTextView::SalInstanceTextView(VclMultiLineEdit* pTextView, SalInstanceBuilder* pBuilder, 5529 bool bTakeOwnership) 5530 : SalInstanceContainer(pTextView, pBuilder, bTakeOwnership) 5531 , m_xTextView(pTextView) 5532 { 5533 m_xTextView->SetModifyHdl(LINK(this, SalInstanceTextView, ChangeHdl)); 5534 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5535 m_aOrigVScrollHdl = rVertScrollBar.GetScrollHdl(); 5536 rVertScrollBar.SetScrollHdl(LINK(this, SalInstanceTextView, VscrollHdl)); 5537 } 5538 5539 void SalInstanceTextView::set_text(const OUString& rText) 5540 { 5541 disable_notify_events(); 5542 m_xTextView->SetText(rText); 5543 enable_notify_events(); 5544 } 5545 5546 void SalInstanceTextView::replace_selection(const OUString& rText) 5547 { 5548 disable_notify_events(); 5549 m_xTextView->ReplaceSelected(rText); 5550 enable_notify_events(); 5551 } 5552 5553 OUString SalInstanceTextView::get_text() const { return m_xTextView->GetText(); } 5554 5555 bool SalInstanceTextView::get_selection_bounds(int& rStartPos, int& rEndPos) 5556 { 5557 const Selection& rSelection = m_xTextView->GetSelection(); 5558 rStartPos = rSelection.Min(); 5559 rEndPos = rSelection.Max(); 5560 return rSelection.Len(); 5561 } 5562 5563 void SalInstanceTextView::select_region(int nStartPos, int nEndPos) 5564 { 5565 disable_notify_events(); 5566 long nStart = nStartPos < 0 ? SELECTION_MAX : nStartPos; 5567 long nEnd = nEndPos < 0 ? SELECTION_MAX : nEndPos; 5568 m_xTextView->SetSelection(Selection(nStart, nEnd)); 5569 enable_notify_events(); 5570 } 5571 5572 void SalInstanceTextView::set_editable(bool bEditable) { m_xTextView->SetReadOnly(!bEditable); } 5573 bool SalInstanceTextView::get_editable() const { return !m_xTextView->IsReadOnly(); } 5574 void SalInstanceTextView::set_max_length(int nChars) { m_xTextView->SetMaxTextLen(nChars); } 5575 5576 void SalInstanceTextView::set_monospace(bool bMonospace) 5577 { 5578 vcl::Font aOrigFont = m_xTextView->GetControlFont(); 5579 vcl::Font aFont; 5580 if (bMonospace) 5581 aFont = OutputDevice::GetDefaultFont(DefaultFontType::UI_FIXED, LANGUAGE_DONTKNOW, 5582 GetDefaultFontFlags::OnlyOne, m_xTextView); 5583 else 5584 aFont = Application::GetSettings().GetStyleSettings().GetFieldFont(); 5585 aFont.SetFontHeight(aOrigFont.GetFontHeight()); 5586 m_xTextView->SetFont(aFont); 5587 m_xTextView->SetControlFont(aFont); 5588 } 5589 5590 void SalInstanceTextView::connect_cursor_position(const Link<TextView&, void>& rLink) 5591 { 5592 assert(!m_aCursorPositionHdl.IsSet()); 5593 m_xTextView->AddEventListener(LINK(this, SalInstanceTextView, CursorListener)); 5594 weld::TextView::connect_cursor_position(rLink); 5595 } 5596 5597 bool SalInstanceTextView::can_move_cursor_with_up() const 5598 { 5599 bool bNoSelection = !m_xTextView->GetSelection(); 5600 return !bNoSelection || m_xTextView->CanUp(); 5601 } 5602 5603 bool SalInstanceTextView::can_move_cursor_with_down() const 5604 { 5605 bool bNoSelection = !m_xTextView->GetSelection(); 5606 return !bNoSelection || m_xTextView->CanDown(); 5607 } 5608 5609 void SalInstanceTextView::cut_clipboard() 5610 { 5611 m_xTextView->Cut(); 5612 } 5613 5614 void SalInstanceTextView::copy_clipboard() 5615 { 5616 m_xTextView->Copy(); 5617 } 5618 5619 void SalInstanceTextView::paste_clipboard() 5620 { 5621 m_xTextView->Paste(); 5622 } 5623 5624 void SalInstanceTextView::set_alignment(TxtAlign eXAlign) 5625 { 5626 ::set_alignment(*m_xTextView, eXAlign); 5627 } 5628 5629 int SalInstanceTextView::vadjustment_get_value() const 5630 { 5631 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5632 return rVertScrollBar.GetThumbPos(); 5633 } 5634 5635 void SalInstanceTextView::vadjustment_set_value(int value) 5636 { 5637 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5638 rVertScrollBar.SetThumbPos(value); 5639 m_aOrigVScrollHdl.Call(&rVertScrollBar); 5640 } 5641 5642 int SalInstanceTextView::vadjustment_get_upper() const 5643 { 5644 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5645 return rVertScrollBar.GetRangeMax(); 5646 } 5647 5648 int SalInstanceTextView::vadjustment_get_lower() const 5649 { 5650 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5651 return rVertScrollBar.GetRangeMin(); 5652 } 5653 5654 int SalInstanceTextView::vadjustment_get_page_size() const 5655 { 5656 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5657 return rVertScrollBar.GetVisibleSize(); 5658 } 5659 5660 bool SalInstanceTextView::has_focus() const 5661 { 5662 return m_xTextView->HasChildPathFocus(); 5663 } 5664 5665 SalInstanceTextView::~SalInstanceTextView() 5666 { 5667 if (!m_xTextView->IsDisposed()) 5668 { 5669 if (m_aCursorPositionHdl.IsSet()) 5670 m_xTextView->RemoveEventListener(LINK(this, SalInstanceTextView, CursorListener)); 5671 m_xTextView->SetModifyHdl(Link<Edit&, void>()); 5672 ScrollBar& rVertScrollBar = m_xTextView->GetVScrollBar(); 5673 rVertScrollBar.SetScrollHdl(m_aOrigVScrollHdl); 5674 } 5675 } 5676 5677 IMPL_LINK(SalInstanceTextView, VscrollHdl, ScrollBar*, pScrollBar, void) 5678 { 5679 signal_vadjustment_changed(); 5680 m_aOrigVScrollHdl.Call(pScrollBar); 5681 } 5682 5683 IMPL_LINK_NOARG(SalInstanceTextView, ChangeHdl, Edit&, void) { signal_changed(); } 5684 5685 IMPL_LINK(SalInstanceTextView, CursorListener, VclWindowEvent&, rEvent, void) 5686 { 5687 if (notify_events_disabled()) 5688 return; 5689 if (rEvent.GetId() == VclEventId::EditSelectionChanged 5690 || rEvent.GetId() == VclEventId::EditCaretChanged) 5691 signal_cursor_position(); 5692 } 5693 5694 namespace 5695 { 5696 class SalInstanceExpander : public SalInstanceContainer, public virtual weld::Expander 5697 { 5698 private: 5699 VclPtr<VclExpander> m_xExpander; 5700 5701 DECL_LINK(ExpandedHdl, VclExpander&, void); 5702 5703 public: 5704 SalInstanceExpander(VclExpander* pExpander, SalInstanceBuilder* pBuilder, bool bTakeOwnership) 5705 : SalInstanceContainer(pExpander, pBuilder, bTakeOwnership) 5706 , m_xExpander(pExpander) 5707 { 5708 m_xExpander->SetExpandedHdl(LINK(this, SalInstanceExpander, ExpandedHdl)); 5709 } 5710 5711 virtual bool get_expanded() const override { return m_xExpander->get_expanded(); } 5712 5713 virtual void set_expanded(bool bExpand) override { m_xExpander->set_expanded(bExpand); } 5714 5715 virtual ~SalInstanceExpander() override 5716 { 5717 m_xExpander->SetExpandedHdl(Link<VclExpander&, void>()); 5718 } 5719 }; 5720 5721 } 5722 5723 IMPL_LINK_NOARG(SalInstanceExpander, ExpandedHdl, VclExpander&, void) { signal_expanded(); } 5724 5725 // SalInstanceWidget has a generic listener for all these 5726 // events, ignore the ones we have specializations for 5727 // in VclDrawingArea 5728 void SalInstanceDrawingArea::HandleEventListener(VclWindowEvent& rEvent) 5729 { 5730 if (rEvent.GetId() == VclEventId::WindowResize) 5731 return; 5732 SalInstanceWidget::HandleEventListener(rEvent); 5733 } 5734 5735 void SalInstanceDrawingArea::HandleMouseEventListener(VclSimpleEvent& rEvent) 5736 { 5737 if (rEvent.GetId() == VclEventId::WindowMouseButtonDown 5738 || rEvent.GetId() == VclEventId::WindowMouseButtonUp 5739 || rEvent.GetId() == VclEventId::WindowMouseMove) 5740 { 5741 return; 5742 } 5743 SalInstanceWidget::HandleMouseEventListener(rEvent); 5744 } 5745 5746 bool SalInstanceDrawingArea::HandleKeyEventListener(VclWindowEvent& /*rEvent*/) { return false; } 5747 5748 SalInstanceDrawingArea::SalInstanceDrawingArea(VclDrawingArea* pDrawingArea, SalInstanceBuilder* pBuilder, 5749 const a11yref& rAlly, FactoryFunction pUITestFactoryFunction, 5750 void* pUserData, bool bTakeOwnership) 5751 : SalInstanceWidget(pDrawingArea, pBuilder, bTakeOwnership) 5752 , m_xDrawingArea(pDrawingArea) 5753 { 5754 m_xDrawingArea->SetAccessible(rAlly); 5755 m_xDrawingArea->SetUITestFactory(std::move(pUITestFactoryFunction), pUserData); 5756 m_xDrawingArea->SetPaintHdl(LINK(this, SalInstanceDrawingArea, PaintHdl)); 5757 m_xDrawingArea->SetResizeHdl(LINK(this, SalInstanceDrawingArea, ResizeHdl)); 5758 m_xDrawingArea->SetMousePressHdl(LINK(this, SalInstanceDrawingArea, MousePressHdl)); 5759 m_xDrawingArea->SetMouseMoveHdl(LINK(this, SalInstanceDrawingArea, MouseMoveHdl)); 5760 m_xDrawingArea->SetMouseReleaseHdl(LINK(this, SalInstanceDrawingArea, MouseReleaseHdl)); 5761 m_xDrawingArea->SetKeyPressHdl(LINK(this, SalInstanceDrawingArea, KeyPressHdl)); 5762 m_xDrawingArea->SetKeyReleaseHdl(LINK(this, SalInstanceDrawingArea, KeyReleaseHdl)); 5763 m_xDrawingArea->SetStyleUpdatedHdl(LINK(this, SalInstanceDrawingArea, StyleUpdatedHdl)); 5764 m_xDrawingArea->SetCommandHdl(LINK(this, SalInstanceDrawingArea, CommandHdl)); 5765 m_xDrawingArea->SetQueryTooltipHdl(LINK(this, SalInstanceDrawingArea, QueryTooltipHdl)); 5766 m_xDrawingArea->SetStartDragHdl(LINK(this, SalInstanceDrawingArea, StartDragHdl)); 5767 } 5768 5769 void SalInstanceDrawingArea::queue_draw() { m_xDrawingArea->Invalidate(); } 5770 5771 void SalInstanceDrawingArea::queue_draw_area(int x, int y, int width, int height) 5772 { 5773 m_xDrawingArea->Invalidate(tools::Rectangle(Point(x, y), Size(width, height))); 5774 } 5775 5776 void SalInstanceDrawingArea::queue_resize() { m_xDrawingArea->queue_resize(); } 5777 5778 void SalInstanceDrawingArea::connect_size_allocate(const Link<const Size&, void>& rLink) 5779 { 5780 weld::Widget::connect_size_allocate(rLink); 5781 } 5782 5783 void SalInstanceDrawingArea::connect_key_press(const Link<const KeyEvent&, bool>& rLink) 5784 { 5785 weld::Widget::connect_key_press(rLink); 5786 } 5787 5788 void SalInstanceDrawingArea::connect_key_release(const Link<const KeyEvent&, bool>& rLink) 5789 { 5790 weld::Widget::connect_key_release(rLink); 5791 } 5792 5793 void SalInstanceDrawingArea::set_cursor(PointerStyle ePointerStyle) 5794 { 5795 m_xDrawingArea->SetPointer(ePointerStyle); 5796 } 5797 5798 a11yref SalInstanceDrawingArea::get_accessible_parent() 5799 { 5800 vcl::Window* pParent = m_xDrawingArea->GetParent(); 5801 if (pParent) 5802 return pParent->GetAccessible(); 5803 return css::uno::Reference<css::accessibility::XAccessible>(); 5804 } 5805 5806 a11yrelationset SalInstanceDrawingArea::get_accessible_relation_set() 5807 { 5808 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper; 5809 css::uno::Reference<css::accessibility::XAccessibleRelationSet> xSet = pRelationSetHelper; 5810 vcl::Window* pWindow = m_xDrawingArea.get(); 5811 if (pWindow) 5812 { 5813 vcl::Window* pLabeledBy = pWindow->GetAccessibleRelationLabeledBy(); 5814 if (pLabeledBy && pLabeledBy != pWindow) 5815 { 5816 css::uno::Sequence<css::uno::Reference<css::uno::XInterface>> aSequence{ 5817 pLabeledBy->GetAccessible() 5818 }; 5819 pRelationSetHelper->AddRelation(css::accessibility::AccessibleRelation( 5820 css::accessibility::AccessibleRelationType::LABELED_BY, aSequence)); 5821 } 5822 vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf(); 5823 if (pMemberOf && pMemberOf != pWindow) 5824 { 5825 css::uno::Sequence<css::uno::Reference<css::uno::XInterface>> aSequence{ 5826 pMemberOf->GetAccessible() 5827 }; 5828 pRelationSetHelper->AddRelation(css::accessibility::AccessibleRelation( 5829 css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence)); 5830 } 5831 } 5832 return xSet; 5833 } 5834 5835 Point SalInstanceDrawingArea::get_accessible_location() 5836 { 5837 return m_xDrawingArea->OutputToAbsoluteScreenPixel(Point()); 5838 } 5839 5840 void SalInstanceDrawingArea::enable_drag_source(rtl::Reference<TransferDataContainer>& rHelper, 5841 sal_uInt8 eDNDConstants) 5842 { 5843 m_xDrawingArea->SetDragHelper(rHelper, eDNDConstants); 5844 } 5845 5846 SalInstanceDrawingArea::~SalInstanceDrawingArea() 5847 { 5848 m_xDrawingArea->SetQueryTooltipHdl(Link<tools::Rectangle&, OUString>()); 5849 m_xDrawingArea->SetCommandHdl(Link<const CommandEvent&, bool>()); 5850 m_xDrawingArea->SetStyleUpdatedHdl(Link<VclDrawingArea&, void>()); 5851 m_xDrawingArea->SetMousePressHdl(Link<const MouseEvent&, bool>()); 5852 m_xDrawingArea->SetMouseMoveHdl(Link<const MouseEvent&, bool>()); 5853 m_xDrawingArea->SetMouseReleaseHdl(Link<const MouseEvent&, bool>()); 5854 m_xDrawingArea->SetKeyPressHdl(Link<const KeyEvent&, bool>()); 5855 m_xDrawingArea->SetKeyReleaseHdl(Link<const KeyEvent&, bool>()); 5856 m_xDrawingArea->SetResizeHdl(Link<const Size&, void>()); 5857 m_xDrawingArea->SetPaintHdl( 5858 Link<std::pair<vcl::RenderContext&, const tools::Rectangle&>, void>()); 5859 } 5860 5861 OutputDevice& SalInstanceDrawingArea::get_ref_device() { return *m_xDrawingArea; } 5862 5863 void SalInstanceDrawingArea::click(const Point& rPos) 5864 { 5865 MouseEvent aEvent(rPos); 5866 m_xDrawingArea->MouseButtonDown(aEvent); 5867 m_xDrawingArea->MouseButtonUp(aEvent); 5868 } 5869 5870 IMPL_LINK(SalInstanceDrawingArea, PaintHdl, target_and_area, aPayload, void) 5871 { 5872 m_aDrawHdl.Call(aPayload); 5873 tools::Rectangle aFocusRect(m_aGetFocusRectHdl.Call(*this)); 5874 if (!aFocusRect.IsEmpty()) 5875 DrawFocusRect(aPayload.first, aFocusRect); 5876 } 5877 5878 IMPL_LINK(SalInstanceDrawingArea, ResizeHdl, const Size&, rSize, void) 5879 { 5880 m_aSizeAllocateHdl.Call(rSize); 5881 } 5882 5883 IMPL_LINK(SalInstanceDrawingArea, MousePressHdl, const MouseEvent&, rEvent, bool) 5884 { 5885 return m_aMousePressHdl.Call(rEvent); 5886 } 5887 5888 IMPL_LINK(SalInstanceDrawingArea, MouseMoveHdl, const MouseEvent&, rEvent, bool) 5889 { 5890 return m_aMouseMotionHdl.Call(rEvent); 5891 } 5892 5893 IMPL_LINK(SalInstanceDrawingArea, MouseReleaseHdl, const MouseEvent&, rEvent, bool) 5894 { 5895 return m_aMouseReleaseHdl.Call(rEvent); 5896 } 5897 5898 IMPL_LINK(SalInstanceDrawingArea, KeyPressHdl, const KeyEvent&, rEvent, bool) 5899 { 5900 return m_aKeyPressHdl.Call(rEvent); 5901 } 5902 5903 IMPL_LINK(SalInstanceDrawingArea, KeyReleaseHdl, const KeyEvent&, rEvent, bool) 5904 { 5905 return m_aKeyReleaseHdl.Call(rEvent); 5906 } 5907 5908 IMPL_LINK_NOARG(SalInstanceDrawingArea, StyleUpdatedHdl, VclDrawingArea&, void) 5909 { 5910 m_aStyleUpdatedHdl.Call(*this); 5911 } 5912 5913 IMPL_LINK(SalInstanceDrawingArea, CommandHdl, const CommandEvent&, rEvent, bool) 5914 { 5915 return m_aCommandHdl.Call(rEvent); 5916 } 5917 5918 IMPL_LINK(SalInstanceDrawingArea, QueryTooltipHdl, tools::Rectangle&, rHelpArea, OUString) 5919 { 5920 return m_aQueryTooltipHdl.Call(rHelpArea); 5921 } 5922 5923 IMPL_LINK_NOARG(SalInstanceDrawingArea, StartDragHdl, VclDrawingArea*, bool) 5924 { 5925 if (m_aDragBeginHdl.Call(*this)) 5926 return true; 5927 return false; 5928 } 5929 5930 SalInstanceComboBoxWithoutEdit::SalInstanceComboBoxWithoutEdit(ListBox* pListBox, SalInstanceBuilder* pBuilder, 5931 bool bTakeOwnership) 5932 : SalInstanceComboBox<ListBox>(pListBox, pBuilder, bTakeOwnership) 5933 { 5934 m_xComboBox->SetSelectHdl(LINK(this, SalInstanceComboBoxWithoutEdit, SelectHdl)); 5935 } 5936 5937 OUString SalInstanceComboBoxWithoutEdit::get_active_text() const { return m_xComboBox->GetSelectedEntry(); } 5938 5939 void SalInstanceComboBoxWithoutEdit::remove(int pos) { m_xComboBox->RemoveEntry(pos); } 5940 5941 void SalInstanceComboBoxWithoutEdit::insert(int pos, const OUString& rStr, const OUString* pId, 5942 const OUString* pIconName, VirtualDevice* pImageSurface) 5943 { 5944 auto nInsertPos = pos == -1 ? COMBOBOX_APPEND : pos; 5945 sal_Int32 nInsertedAt; 5946 if (!pIconName && !pImageSurface) 5947 nInsertedAt = m_xComboBox->InsertEntry(rStr, nInsertPos); 5948 else if (pIconName) 5949 nInsertedAt = m_xComboBox->InsertEntry(rStr, createImage(*pIconName), nInsertPos); 5950 else 5951 nInsertedAt = m_xComboBox->InsertEntry(rStr, createImage(*pImageSurface), nInsertPos); 5952 if (pId) 5953 { 5954 m_aUserData.emplace_back(std::make_unique<OUString>(*pId)); 5955 m_xComboBox->SetEntryData(nInsertedAt, m_aUserData.back().get()); 5956 } 5957 } 5958 5959 void SalInstanceComboBoxWithoutEdit::insert_separator(int pos, const OUString& /*rId*/) 5960 { 5961 auto nInsertPos = pos == -1 ? m_xComboBox->GetEntryCount() : pos; 5962 m_xComboBox->AddSeparator(nInsertPos - 1); 5963 } 5964 5965 bool SalInstanceComboBoxWithoutEdit::has_entry() const { return false; } 5966 5967 bool SalInstanceComboBoxWithoutEdit::changed_by_direct_pick() const { return true; } 5968 5969 void SalInstanceComboBoxWithoutEdit::set_entry_message_type(weld::EntryMessageType /*eType*/) 5970 { 5971 assert(false); 5972 } 5973 5974 void SalInstanceComboBoxWithoutEdit::set_entry_text(const OUString& /*rText*/) { assert(false); } 5975 5976 void SalInstanceComboBoxWithoutEdit::select_entry_region(int /*nStartPos*/, int /*nEndPos*/) { assert(false); } 5977 5978 bool SalInstanceComboBoxWithoutEdit::get_entry_selection_bounds(int& /*rStartPos*/, int& /*rEndPos*/) 5979 { 5980 assert(false); 5981 return false; 5982 } 5983 5984 void SalInstanceComboBoxWithoutEdit::set_entry_width_chars(int /*nChars*/) { assert(false); } 5985 5986 void SalInstanceComboBoxWithoutEdit::set_entry_max_length(int /*nChars*/) { assert(false); } 5987 5988 void SalInstanceComboBoxWithoutEdit::set_entry_completion(bool, bool) { assert(false); } 5989 5990 void SalInstanceComboBoxWithoutEdit::set_entry_placeholder_text(const OUString&) { assert(false); } 5991 5992 void SalInstanceComboBoxWithoutEdit::set_entry_editable(bool /*bEditable*/) { assert(false); } 5993 5994 void SalInstanceComboBoxWithoutEdit::cut_entry_clipboard() { assert(false); } 5995 5996 void SalInstanceComboBoxWithoutEdit::copy_entry_clipboard() { assert(false); } 5997 5998 void SalInstanceComboBoxWithoutEdit::paste_entry_clipboard() { assert(false); } 5999 6000 void SalInstanceComboBoxWithoutEdit::set_entry_font(const vcl::Font&) { assert(false); } 6001 6002 vcl::Font SalInstanceComboBoxWithoutEdit::get_entry_font() { assert(false); return vcl::Font(); } 6003 6004 void SalInstanceComboBoxWithoutEdit::set_custom_renderer(bool /*bOn*/) 6005 { 6006 assert(false && "not implemented"); 6007 } 6008 6009 int SalInstanceComboBoxWithoutEdit::get_max_mru_count() const 6010 { 6011 assert(false && "not implemented"); 6012 return 0; 6013 } 6014 6015 void SalInstanceComboBoxWithoutEdit::set_max_mru_count(int) 6016 { 6017 assert(false && "not implemented"); 6018 } 6019 6020 OUString SalInstanceComboBoxWithoutEdit::get_mru_entries() const 6021 { 6022 assert(false && "not implemented"); 6023 return OUString(); 6024 } 6025 6026 void SalInstanceComboBoxWithoutEdit::set_mru_entries(const OUString&) 6027 { 6028 assert(false && "not implemented"); 6029 } 6030 6031 void SalInstanceComboBoxWithoutEdit::HandleEventListener(VclWindowEvent& rEvent) 6032 { 6033 CallHandleEventListener(rEvent); 6034 } 6035 6036 SalInstanceComboBoxWithoutEdit::~SalInstanceComboBoxWithoutEdit() 6037 { 6038 m_xComboBox->SetSelectHdl(Link<ListBox&, void>()); 6039 } 6040 6041 IMPL_LINK_NOARG(SalInstanceComboBoxWithoutEdit, SelectHdl, ListBox&, void) 6042 { 6043 return signal_changed(); 6044 } 6045 6046 SalInstanceComboBoxWithEdit::SalInstanceComboBoxWithEdit(::ComboBox* pComboBox, SalInstanceBuilder* pBuilder, 6047 bool bTakeOwnership) 6048 : SalInstanceComboBox<::ComboBox>(pComboBox, pBuilder, bTakeOwnership) 6049 , m_aTextFilter(m_aEntryInsertTextHdl) 6050 , m_bInSelect(false) 6051 { 6052 m_xComboBox->SetModifyHdl(LINK(this, SalInstanceComboBoxWithEdit, ChangeHdl)); 6053 m_xComboBox->SetSelectHdl(LINK(this, SalInstanceComboBoxWithEdit, SelectHdl)); 6054 m_xComboBox->SetEntryActivateHdl(LINK(this, SalInstanceComboBoxWithEdit, EntryActivateHdl)); 6055 m_xComboBox->SetTextFilter(&m_aTextFilter); 6056 } 6057 6058 bool SalInstanceComboBoxWithEdit::has_entry() const { return true; } 6059 6060 bool SalInstanceComboBoxWithEdit::changed_by_direct_pick() const 6061 { 6062 return m_bInSelect && !m_xComboBox->IsModifyByKeyboard() && !m_xComboBox->IsTravelSelect(); 6063 } 6064 6065 void SalInstanceComboBoxWithEdit::set_entry_message_type(weld::EntryMessageType eType) 6066 { 6067 switch (eType) 6068 { 6069 case weld::EntryMessageType::Normal: 6070 m_xComboBox->SetControlForeground(); 6071 break; 6072 case weld::EntryMessageType::Warning: 6073 m_xComboBox->SetControlForeground(COL_YELLOW); 6074 break; 6075 case weld::EntryMessageType::Error: 6076 m_xComboBox->SetControlForeground(Color(0xf0, 0, 0)); 6077 break; 6078 } 6079 } 6080 6081 OUString SalInstanceComboBoxWithEdit::get_active_text() const { return m_xComboBox->GetText(); } 6082 6083 void SalInstanceComboBoxWithEdit::remove(int pos) { m_xComboBox->RemoveEntryAt(pos); } 6084 6085 void SalInstanceComboBoxWithEdit::insert(int pos, const OUString& rStr, const OUString* pId, 6086 const OUString* pIconName, VirtualDevice* pImageSurface) 6087 { 6088 auto nInsertPos = pos == -1 ? COMBOBOX_APPEND : pos; 6089 sal_Int32 nInsertedAt; 6090 if (!pIconName && !pImageSurface) 6091 nInsertedAt = m_xComboBox->InsertEntry(rStr, nInsertPos); 6092 else if (pIconName) 6093 nInsertedAt 6094 = m_xComboBox->InsertEntryWithImage(rStr, createImage(*pIconName), nInsertPos); 6095 else 6096 nInsertedAt 6097 = m_xComboBox->InsertEntryWithImage(rStr, createImage(*pImageSurface), nInsertPos); 6098 if (pId) 6099 { 6100 m_aUserData.emplace_back(std::make_unique<OUString>(*pId)); 6101 m_xComboBox->SetEntryData(nInsertedAt, m_aUserData.back().get()); 6102 } 6103 } 6104 6105 void SalInstanceComboBoxWithEdit::insert_separator(int pos, const OUString& /*rId*/) 6106 { 6107 auto nInsertPos = pos == -1 ? m_xComboBox->GetEntryCount() : pos; 6108 m_xComboBox->AddSeparator(nInsertPos - 1); 6109 } 6110 6111 void SalInstanceComboBoxWithEdit::set_entry_text(const OUString& rText) { m_xComboBox->SetText(rText); } 6112 6113 void SalInstanceComboBoxWithEdit::set_entry_width_chars(int nChars) 6114 { 6115 m_xComboBox->SetWidthInChars(nChars); 6116 } 6117 6118 void SalInstanceComboBoxWithEdit::set_entry_max_length(int nChars) { m_xComboBox->SetMaxTextLen(nChars); } 6119 6120 void SalInstanceComboBoxWithEdit::set_entry_completion(bool bEnable, bool bCaseSensitive) 6121 { 6122 m_xComboBox->EnableAutocomplete(bEnable, bCaseSensitive); 6123 } 6124 6125 void SalInstanceComboBoxWithEdit::set_entry_placeholder_text(const OUString& rText) 6126 { 6127 m_xComboBox->SetPlaceholderText(rText); 6128 } 6129 6130 void SalInstanceComboBoxWithEdit::set_entry_editable(bool bEditable) 6131 { 6132 m_xComboBox->SetReadOnly(!bEditable); 6133 } 6134 6135 void SalInstanceComboBoxWithEdit::cut_entry_clipboard() 6136 { 6137 m_xComboBox->Cut(); 6138 } 6139 6140 void SalInstanceComboBoxWithEdit::copy_entry_clipboard() 6141 { 6142 m_xComboBox->Copy(); 6143 } 6144 6145 void SalInstanceComboBoxWithEdit::paste_entry_clipboard() 6146 { 6147 m_xComboBox->Paste(); 6148 } 6149 6150 void SalInstanceComboBoxWithEdit::select_entry_region(int nStartPos, int nEndPos) 6151 { 6152 m_xComboBox->SetSelection(Selection(nStartPos, nEndPos < 0 ? SELECTION_MAX : nEndPos)); 6153 } 6154 6155 bool SalInstanceComboBoxWithEdit::get_entry_selection_bounds(int& rStartPos, int& rEndPos) 6156 { 6157 const Selection& rSelection = m_xComboBox->GetSelection(); 6158 rStartPos = rSelection.Min(); 6159 rEndPos = rSelection.Max(); 6160 return rSelection.Len(); 6161 } 6162 6163 void SalInstanceComboBoxWithEdit::set_entry_font(const vcl::Font& rFont) 6164 { 6165 Edit* pEdit = m_xComboBox->GetSubEdit(); 6166 assert(pEdit); 6167 pEdit->SetPointFont(*pEdit, rFont); 6168 m_xComboBox->SetControlFont(rFont); // tdf#134601 set it as control font to take effect properly 6169 pEdit->Invalidate(); 6170 } 6171 6172 vcl::Font SalInstanceComboBoxWithEdit::get_entry_font() 6173 { 6174 Edit* pEdit = m_xComboBox->GetSubEdit(); 6175 assert(pEdit); 6176 return pEdit->GetPointFont(*pEdit); 6177 } 6178 6179 void SalInstanceComboBoxWithEdit::set_custom_renderer(bool bOn) 6180 { 6181 if (m_xComboBox->IsUserDrawEnabled() == bOn) 6182 return; 6183 6184 auto nOldEntryHeight = m_xComboBox->GetDropDownEntryHeight(); 6185 auto nDropDownLineCount = m_xComboBox->GetDropDownLineCount(); 6186 6187 m_xComboBox->EnableUserDraw(bOn); 6188 if (bOn) 6189 m_xComboBox->SetUserDrawHdl(LINK(this, SalInstanceComboBoxWithEdit, UserDrawHdl)); 6190 else 6191 m_xComboBox->SetUserDrawHdl(Link<UserDrawEvent*, void>()); 6192 6193 // adjust the line count to fit approx the height it would have been before 6194 // changing the renderer 6195 auto nNewEntryHeight = m_xComboBox->GetDropDownEntryHeight(); 6196 double fRatio = nOldEntryHeight / static_cast<double>(nNewEntryHeight); 6197 m_xComboBox->SetDropDownLineCount(nDropDownLineCount * fRatio); 6198 } 6199 6200 int SalInstanceComboBoxWithEdit::get_max_mru_count() const 6201 { 6202 return m_xComboBox->GetMaxMRUCount(); 6203 } 6204 6205 void SalInstanceComboBoxWithEdit::set_max_mru_count(int nCount) 6206 { 6207 return m_xComboBox->SetMaxMRUCount(nCount); 6208 } 6209 6210 OUString SalInstanceComboBoxWithEdit::get_mru_entries() const 6211 { 6212 return m_xComboBox->GetMRUEntries(); 6213 } 6214 6215 void SalInstanceComboBoxWithEdit::set_mru_entries(const OUString& rEntries) 6216 { 6217 m_xComboBox->SetMRUEntries(rEntries); 6218 } 6219 6220 void SalInstanceComboBoxWithEdit::HandleEventListener(VclWindowEvent& rEvent) 6221 { 6222 if (rEvent.GetId() == VclEventId::DropdownPreOpen) 6223 { 6224 Size aRowSize(signal_custom_get_size(*m_xComboBox)); 6225 m_xComboBox->SetUserItemSize(aRowSize); 6226 } 6227 CallHandleEventListener(rEvent); 6228 } 6229 6230 SalInstanceComboBoxWithEdit::~SalInstanceComboBoxWithEdit() 6231 { 6232 m_xComboBox->SetTextFilter(nullptr); 6233 m_xComboBox->SetEntryActivateHdl(Link<Edit&, bool>()); 6234 m_xComboBox->SetModifyHdl(Link<Edit&, void>()); 6235 m_xComboBox->SetSelectHdl(Link<::ComboBox&, void>()); 6236 } 6237 6238 IMPL_LINK_NOARG(SalInstanceComboBoxWithEdit, ChangeHdl, Edit&, void) 6239 { 6240 if (!m_xComboBox->IsSyntheticModify()) // SelectHdl will be called 6241 signal_changed(); 6242 } 6243 6244 IMPL_LINK_NOARG(SalInstanceComboBoxWithEdit, SelectHdl, ::ComboBox&, void) 6245 { 6246 m_bInSelect = true; 6247 signal_changed(); 6248 m_bInSelect = false; 6249 } 6250 6251 IMPL_LINK_NOARG(SalInstanceComboBoxWithEdit, EntryActivateHdl, Edit&, bool) 6252 { 6253 return m_aEntryActivateHdl.Call(*this); 6254 } 6255 6256 IMPL_LINK(SalInstanceComboBoxWithEdit, UserDrawHdl, UserDrawEvent*, pEvent, void) 6257 { 6258 call_signal_custom_render(pEvent); 6259 } 6260 6261 class SalInstanceEntryTreeView : public SalInstanceContainer, public virtual weld::EntryTreeView 6262 { 6263 private: 6264 DECL_LINK(AutocompleteHdl, Edit&, void); 6265 DECL_LINK(KeyPressListener, VclWindowEvent&, void); 6266 SalInstanceEntry* m_pEntry; 6267 SalInstanceTreeView* m_pTreeView; 6268 bool m_bTreeChange; 6269 6270 public: 6271 SalInstanceEntryTreeView(vcl::Window* pContainer, SalInstanceBuilder* pBuilder, 6272 bool bTakeOwnership, std::unique_ptr<weld::Entry> xEntry, 6273 std::unique_ptr<weld::TreeView> xTreeView) 6274 : EntryTreeView(std::move(xEntry), std::move(xTreeView)) 6275 , SalInstanceContainer(pContainer, pBuilder, bTakeOwnership) 6276 , m_pEntry(dynamic_cast<SalInstanceEntry*>(m_xEntry.get())) 6277 , m_pTreeView(dynamic_cast<SalInstanceTreeView*>(m_xTreeView.get())) 6278 , m_bTreeChange(false) 6279 { 6280 assert(m_pEntry && m_pTreeView); 6281 6282 Edit& rEntry = m_pEntry->getEntry(); 6283 rEntry.SetAutocompleteHdl(LINK(this, SalInstanceEntryTreeView, AutocompleteHdl)); 6284 rEntry.AddEventListener(LINK(this, SalInstanceEntryTreeView, KeyPressListener)); 6285 } 6286 6287 virtual void insert_separator(int /*pos*/, const OUString& /*rId*/) override { assert(false); } 6288 6289 virtual void make_sorted() override 6290 { 6291 vcl::Window* pTreeView = m_pTreeView->getWidget(); 6292 pTreeView->SetStyle(pTreeView->GetStyle() | WB_SORT); 6293 } 6294 6295 virtual void set_entry_completion(bool bEnable, bool /*bCaseSensitive*/) override 6296 { 6297 assert(!bEnable && "not implemented yet"); 6298 (void)bEnable; 6299 Edit& rEntry = m_pEntry->getEntry(); 6300 rEntry.SetAutocompleteHdl(Link<Edit&, void>()); 6301 } 6302 6303 virtual void set_entry_font(const vcl::Font& rFont) override 6304 { 6305 Edit& rEntry = m_pEntry->getEntry(); 6306 rEntry.SetPointFont(rEntry, rFont); 6307 rEntry.Invalidate(); 6308 } 6309 6310 virtual vcl::Font get_entry_font() override 6311 { 6312 Edit& rEntry = m_pEntry->getEntry(); 6313 return rEntry.GetPointFont(rEntry); 6314 } 6315 6316 virtual void set_entry_placeholder_text(const OUString& rText) override 6317 { 6318 Edit& rEntry = m_pEntry->getEntry(); 6319 rEntry.SetPlaceholderText(rText); 6320 } 6321 6322 virtual void set_entry_editable(bool bEditable) override 6323 { 6324 Edit& rEntry = m_pEntry->getEntry(); 6325 rEntry.SetReadOnly(!bEditable); 6326 } 6327 6328 virtual void cut_entry_clipboard() override 6329 { 6330 Edit& rEntry = m_pEntry->getEntry(); 6331 rEntry.Cut(); 6332 } 6333 6334 virtual void copy_entry_clipboard() override 6335 { 6336 Edit& rEntry = m_pEntry->getEntry(); 6337 rEntry.Copy(); 6338 } 6339 6340 virtual void paste_entry_clipboard() override 6341 { 6342 Edit& rEntry = m_pEntry->getEntry(); 6343 rEntry.Paste(); 6344 } 6345 6346 virtual void grab_focus() override { m_xEntry->grab_focus(); } 6347 6348 virtual void connect_focus_in(const Link<Widget&, void>& rLink) override 6349 { 6350 m_xEntry->connect_focus_in(rLink); 6351 } 6352 6353 virtual void connect_focus_out(const Link<Widget&, void>& rLink) override 6354 { 6355 m_xEntry->connect_focus_out(rLink); 6356 } 6357 6358 virtual bool changed_by_direct_pick() const override { return m_bTreeChange; } 6359 6360 virtual void set_custom_renderer(bool /*bOn*/) override 6361 { 6362 assert(false && "not implemented"); 6363 } 6364 6365 virtual int get_max_mru_count() const override 6366 { 6367 assert(false && "not implemented"); 6368 return 0; 6369 } 6370 6371 virtual void set_max_mru_count(int) override 6372 { 6373 assert(false && "not implemented"); 6374 } 6375 6376 virtual OUString get_mru_entries() const override 6377 { 6378 assert(false && "not implemented"); 6379 return OUString(); 6380 } 6381 6382 virtual void set_mru_entries(const OUString&) override 6383 { 6384 assert(false && "not implemented"); 6385 } 6386 6387 virtual void set_item_menu(const OString&, weld::Menu*) override 6388 { 6389 assert(false && "not implemented"); 6390 } 6391 6392 int get_menu_button_width() const override 6393 { 6394 assert(false && "not implemented"); 6395 return 0; 6396 } 6397 6398 VclPtr<VirtualDevice> create_render_virtual_device() const override 6399 { 6400 return VclPtr<VirtualDevice>::Create(); 6401 } 6402 6403 virtual ~SalInstanceEntryTreeView() override 6404 { 6405 Edit& rEntry = m_pEntry->getEntry(); 6406 rEntry.RemoveEventListener(LINK(this, SalInstanceEntryTreeView, KeyPressListener)); 6407 rEntry.SetAutocompleteHdl(Link<Edit&, void>()); 6408 } 6409 }; 6410 6411 IMPL_LINK(SalInstanceEntryTreeView, KeyPressListener, VclWindowEvent&, rEvent, void) 6412 { 6413 if (rEvent.GetId() != VclEventId::WindowKeyInput) 6414 return; 6415 const KeyEvent& rKeyEvent = *static_cast<KeyEvent*>(rEvent.GetData()); 6416 sal_uInt16 nKeyCode = rKeyEvent.GetKeyCode().GetCode(); 6417 if (!(nKeyCode == KEY_UP || nKeyCode == KEY_DOWN || nKeyCode == KEY_PAGEUP 6418 || nKeyCode == KEY_PAGEDOWN)) 6419 return; 6420 6421 m_pTreeView->disable_notify_events(); 6422 auto& rListBox = m_pTreeView->getTreeView(); 6423 if (!rListBox.FirstSelected()) 6424 { 6425 if (SvTreeListEntry* pEntry = rListBox.First()) 6426 rListBox.Select(pEntry, true); 6427 } 6428 else 6429 rListBox.KeyInput(rKeyEvent); 6430 m_xEntry->set_text(m_xTreeView->get_selected_text()); 6431 m_xEntry->select_region(0, -1); 6432 m_pTreeView->enable_notify_events(); 6433 m_bTreeChange = true; 6434 m_pEntry->fire_signal_changed(); 6435 m_bTreeChange = false; 6436 } 6437 6438 IMPL_LINK(SalInstanceEntryTreeView, AutocompleteHdl, Edit&, rEdit, void) 6439 { 6440 Selection aSel = rEdit.GetSelection(); 6441 6442 OUString aFullText = rEdit.GetText(); 6443 OUString aStartText = aFullText.copy(0, static_cast<sal_Int32>(aSel.Max())); 6444 6445 int nPos = -1; 6446 int nCount = m_xTreeView->n_children(); 6447 for (int i = 0; i < nCount; ++i) 6448 { 6449 if (m_xTreeView->get_text(i).startsWithIgnoreAsciiCase(aStartText)) 6450 { 6451 nPos = i; 6452 break; 6453 } 6454 } 6455 6456 m_xTreeView->select(nPos); 6457 6458 if (nPos != -1) 6459 { 6460 OUString aText = m_xTreeView->get_text(nPos); 6461 Selection aSelection(aText.getLength(), aStartText.getLength()); 6462 rEdit.SetText(aText, aSelection); 6463 } 6464 } 6465 6466 SalInstanceBuilder::SalInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot, 6467 const OUString& rUIFile, const css::uno::Reference<css::frame::XFrame>& rFrame) 6468 : weld::Builder() 6469 , m_xBuilder(new VclBuilder(pParent, rUIRoot, rUIFile, OString(), rFrame, false)) 6470 { 6471 } 6472 6473 std::unique_ptr<weld::MessageDialog> SalInstanceBuilder::weld_message_dialog(const OString& id, 6474 bool bTakeOwnership) 6475 { 6476 MessageDialog* pMessageDialog = m_xBuilder->get<MessageDialog>(id); 6477 std::unique_ptr<weld::MessageDialog> pRet( 6478 pMessageDialog ? new SalInstanceMessageDialog(pMessageDialog, this, false) : nullptr); 6479 if (bTakeOwnership && pMessageDialog) 6480 { 6481 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); 6482 m_aOwnedToplevel.set(pMessageDialog); 6483 m_xBuilder->drop_ownership(pMessageDialog); 6484 } 6485 return pRet; 6486 } 6487 6488 std::unique_ptr<weld::Dialog> SalInstanceBuilder::weld_dialog(const OString& id, 6489 bool bTakeOwnership) 6490 { 6491 Dialog* pDialog = m_xBuilder->get<Dialog>(id); 6492 std::unique_ptr<weld::Dialog> pRet(pDialog ? new SalInstanceDialog(pDialog, this, false) 6493 : nullptr); 6494 if (bTakeOwnership && pDialog) 6495 { 6496 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); 6497 m_aOwnedToplevel.set(pDialog); 6498 m_xBuilder->drop_ownership(pDialog); 6499 } 6500 return pRet; 6501 } 6502 6503 std::unique_ptr<weld::Assistant> SalInstanceBuilder::weld_assistant(const OString& id, 6504 bool bTakeOwnership) 6505 { 6506 vcl::RoadmapWizard* pDialog = m_xBuilder->get<vcl::RoadmapWizard>(id); 6507 std::unique_ptr<weld::Assistant> pRet(pDialog ? new SalInstanceAssistant(pDialog, this, false) 6508 : nullptr); 6509 if (bTakeOwnership && pDialog) 6510 { 6511 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); 6512 m_aOwnedToplevel.set(pDialog); 6513 m_xBuilder->drop_ownership(pDialog); 6514 } 6515 return pRet; 6516 } 6517 6518 std::unique_ptr<weld::Window> SalInstanceBuilder::create_screenshot_window() 6519 { 6520 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); 6521 6522 vcl::Window* pRoot = m_xBuilder->get_widget_root(); 6523 if (SystemWindow* pWindow = dynamic_cast<SystemWindow*>(pRoot)) 6524 { 6525 std::unique_ptr<weld::Window> xRet(new SalInstanceWindow(pWindow, this, false)); 6526 m_aOwnedToplevel.set(pWindow); 6527 m_xBuilder->drop_ownership(pWindow); 6528 return xRet; 6529 } 6530 6531 VclPtrInstance<Dialog> xDialog(nullptr, WB_HIDE | WB_STDDIALOG | WB_SIZEABLE | WB_CLOSEABLE, 6532 Dialog::InitFlag::NoParent); 6533 xDialog->SetText(utl::ConfigManager::getProductName()); 6534 6535 auto xContentArea = VclPtr<VclVBox>::Create(xDialog, false, 12); 6536 pRoot->SetParent(xContentArea); 6537 assert(pRoot == xContentArea->GetWindow(GetWindowType::FirstChild)); 6538 xContentArea->Show(); 6539 pRoot->Show(); 6540 xDialog->SetHelpId(pRoot->GetHelpId()); 6541 6542 m_aOwnedToplevel.set(xDialog); 6543 6544 return std::unique_ptr<weld::Dialog>(new SalInstanceDialog(xDialog, this, false)); 6545 } 6546 6547 std::unique_ptr<weld::Window> SalInstanceBuilder::weld_window(const OString& id, 6548 bool bTakeOwnership) 6549 { 6550 SystemWindow* pWindow = m_xBuilder->get<SystemWindow>(id); 6551 return pWindow ? std::make_unique<SalInstanceWindow>(pWindow, this, bTakeOwnership) : nullptr; 6552 } 6553 6554 std::unique_ptr<weld::Widget> SalInstanceBuilder::weld_widget(const OString& id, 6555 bool bTakeOwnership) 6556 { 6557 vcl::Window* pWidget = m_xBuilder->get(id); 6558 return pWidget ? std::make_unique<SalInstanceWidget>(pWidget, this, bTakeOwnership) : nullptr; 6559 } 6560 6561 std::unique_ptr<weld::Container> SalInstanceBuilder::weld_container(const OString& id, 6562 bool bTakeOwnership) 6563 { 6564 vcl::Window* pContainer = m_xBuilder->get(id); 6565 return pContainer ? std::make_unique<SalInstanceContainer>(pContainer, this, bTakeOwnership) 6566 : nullptr; 6567 } 6568 6569 std::unique_ptr<weld::Box> SalInstanceBuilder::weld_box(const OString& id, bool bTakeOwnership) 6570 { 6571 VclBox* pContainer = m_xBuilder->get<VclBox>(id); 6572 return pContainer ? std::make_unique<SalInstanceBox>(pContainer, this, bTakeOwnership) 6573 : nullptr; 6574 } 6575 6576 std::unique_ptr<weld::Paned> SalInstanceBuilder::weld_paned(const OString& id, 6577 bool bTakeOwnership) 6578 { 6579 VclPaned* pPaned = m_xBuilder->get<VclPaned>(id); 6580 return pPaned ? std::make_unique<SalInstancePaned>(pPaned, this, bTakeOwnership) 6581 : nullptr; 6582 } 6583 6584 std::unique_ptr<weld::Frame> SalInstanceBuilder::weld_frame(const OString& id, bool bTakeOwnership) 6585 { 6586 VclFrame* pFrame = m_xBuilder->get<VclFrame>(id); 6587 std::unique_ptr<weld::Frame> pRet(pFrame ? new SalInstanceFrame(pFrame, this, false) : nullptr); 6588 if (bTakeOwnership && pFrame) 6589 { 6590 assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); 6591 m_aOwnedToplevel.set(pFrame); 6592 m_xBuilder->drop_ownership(pFrame); 6593 } 6594 return pRet; 6595 } 6596 6597 std::unique_ptr<weld::ScrolledWindow> SalInstanceBuilder::weld_scrolled_window(const OString& id, 6598 bool bTakeOwnership) 6599 { 6600 VclScrolledWindow* pScrolledWindow = m_xBuilder->get<VclScrolledWindow>(id); 6601 return pScrolledWindow 6602 ? std::make_unique<SalInstanceScrolledWindow>(pScrolledWindow, this, bTakeOwnership) 6603 : nullptr; 6604 } 6605 6606 std::unique_ptr<weld::Notebook> SalInstanceBuilder::weld_notebook(const OString& id, 6607 bool bTakeOwnership) 6608 { 6609 vcl::Window* pNotebook = m_xBuilder->get(id); 6610 if (!pNotebook) 6611 return nullptr; 6612 if (pNotebook->GetType() == WindowType::TABCONTROL) 6613 return std::make_unique<SalInstanceNotebook>(static_cast<TabControl*>(pNotebook), this, 6614 bTakeOwnership); 6615 if (pNotebook->GetType() == WindowType::VERTICALTABCONTROL) 6616 return std::make_unique<SalInstanceVerticalNotebook>( 6617 static_cast<VerticalTabControl*>(pNotebook), this, bTakeOwnership); 6618 return nullptr; 6619 } 6620 6621 std::unique_ptr<weld::Button> SalInstanceBuilder::weld_button(const OString& id, 6622 bool bTakeOwnership) 6623 { 6624 Button* pButton = m_xBuilder->get<Button>(id); 6625 return pButton ? std::make_unique<SalInstanceButton>(pButton, this, bTakeOwnership) : nullptr; 6626 } 6627 6628 std::unique_ptr<weld::MenuButton> SalInstanceBuilder::weld_menu_button(const OString& id, 6629 bool bTakeOwnership) 6630 { 6631 MenuButton* pButton = m_xBuilder->get<MenuButton>(id); 6632 return pButton ? std::make_unique<SalInstanceMenuButton>(pButton, this, bTakeOwnership) 6633 : nullptr; 6634 } 6635 6636 std::unique_ptr<weld::LinkButton> SalInstanceBuilder::weld_link_button(const OString& id, 6637 bool bTakeOwnership) 6638 { 6639 FixedHyperlink* pButton = m_xBuilder->get<FixedHyperlink>(id); 6640 return pButton ? std::make_unique<SalInstanceLinkButton>(pButton, this, bTakeOwnership) 6641 : nullptr; 6642 } 6643 6644 std::unique_ptr<weld::ToggleButton> SalInstanceBuilder::weld_toggle_button(const OString& id, 6645 bool bTakeOwnership) 6646 { 6647 PushButton* pToggleButton = m_xBuilder->get<PushButton>(id); 6648 return pToggleButton 6649 ? std::make_unique<SalInstanceToggleButton>(pToggleButton, this, bTakeOwnership) 6650 : nullptr; 6651 } 6652 6653 std::unique_ptr<weld::RadioButton> SalInstanceBuilder::weld_radio_button(const OString& id, 6654 bool bTakeOwnership) 6655 { 6656 RadioButton* pRadioButton = m_xBuilder->get<RadioButton>(id); 6657 return pRadioButton 6658 ? std::make_unique<SalInstanceRadioButton>(pRadioButton, this, bTakeOwnership) 6659 : nullptr; 6660 } 6661 6662 std::unique_ptr<weld::CheckButton> SalInstanceBuilder::weld_check_button(const OString& id, 6663 bool bTakeOwnership) 6664 { 6665 CheckBox* pCheckButton = m_xBuilder->get<CheckBox>(id); 6666 return pCheckButton 6667 ? std::make_unique<SalInstanceCheckButton>(pCheckButton, this, bTakeOwnership) 6668 : nullptr; 6669 } 6670 6671 std::unique_ptr<weld::Scale> SalInstanceBuilder::weld_scale(const OString& id, bool bTakeOwnership) 6672 { 6673 Slider* pSlider = m_xBuilder->get<Slider>(id); 6674 return pSlider ? std::make_unique<SalInstanceScale>(pSlider, this, bTakeOwnership) : nullptr; 6675 } 6676 6677 std::unique_ptr<weld::ProgressBar> SalInstanceBuilder::weld_progress_bar(const OString& id, 6678 bool bTakeOwnership) 6679 { 6680 ::ProgressBar* pProgress = m_xBuilder->get<::ProgressBar>(id); 6681 return pProgress ? std::make_unique<SalInstanceProgressBar>(pProgress, this, bTakeOwnership) 6682 : nullptr; 6683 } 6684 6685 std::unique_ptr<weld::Spinner> SalInstanceBuilder::weld_spinner(const OString& id, 6686 bool bTakeOwnership) 6687 { 6688 Throbber* pThrobber = m_xBuilder->get<Throbber>(id); 6689 return pThrobber ? std::make_unique<SalInstanceSpinner>(pThrobber, this, bTakeOwnership) 6690 : nullptr; 6691 } 6692 6693 std::unique_ptr<weld::Image> SalInstanceBuilder::weld_image(const OString& id, bool bTakeOwnership) 6694 { 6695 FixedImage* pImage = m_xBuilder->get<FixedImage>(id); 6696 return pImage ? std::make_unique<SalInstanceImage>(pImage, this, bTakeOwnership) : nullptr; 6697 } 6698 6699 std::unique_ptr<weld::Calendar> SalInstanceBuilder::weld_calendar(const OString& id, 6700 bool bTakeOwnership) 6701 { 6702 Calendar* pCalendar = m_xBuilder->get<Calendar>(id); 6703 return pCalendar ? std::make_unique<SalInstanceCalendar>(pCalendar, this, bTakeOwnership) 6704 : nullptr; 6705 } 6706 6707 std::unique_ptr<weld::Entry> SalInstanceBuilder::weld_entry(const OString& id, bool bTakeOwnership) 6708 { 6709 Edit* pEntry = m_xBuilder->get<Edit>(id); 6710 return pEntry ? std::make_unique<SalInstanceEntry>(pEntry, this, bTakeOwnership) : nullptr; 6711 } 6712 6713 std::unique_ptr<weld::SpinButton> SalInstanceBuilder::weld_spin_button(const OString& id, 6714 bool bTakeOwnership) 6715 { 6716 FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id); 6717 return pSpinButton ? std::make_unique<SalInstanceSpinButton>(pSpinButton, this, bTakeOwnership) 6718 : nullptr; 6719 } 6720 6721 std::unique_ptr<weld::MetricSpinButton> 6722 SalInstanceBuilder::weld_metric_spin_button(const OString& id, FieldUnit eUnit, bool bTakeOwnership) 6723 { 6724 std::unique_ptr<weld::SpinButton> xButton(weld_spin_button(id, bTakeOwnership)); 6725 if (xButton) 6726 { 6727 SalInstanceSpinButton& rButton = dynamic_cast<SalInstanceSpinButton&>(*xButton); 6728 rButton.SetUseThousandSep(); 6729 } 6730 return std::make_unique<weld::MetricSpinButton>(std::move(xButton), eUnit); 6731 } 6732 6733 std::unique_ptr<weld::FormattedSpinButton> 6734 SalInstanceBuilder::weld_formatted_spin_button(const OString& id, bool bTakeOwnership) 6735 { 6736 FormattedField* pSpinButton = m_xBuilder->get<FormattedField>(id); 6737 return pSpinButton 6738 ? std::make_unique<SalInstanceFormattedSpinButton>(pSpinButton, this, bTakeOwnership) 6739 : nullptr; 6740 } 6741 6742 std::unique_ptr<weld::ComboBox> SalInstanceBuilder::weld_combo_box(const OString& id, 6743 bool bTakeOwnership) 6744 { 6745 vcl::Window* pWidget = m_xBuilder->get(id); 6746 ::ComboBox* pComboBox = dynamic_cast<::ComboBox*>(pWidget); 6747 if (pComboBox) 6748 return std::make_unique<SalInstanceComboBoxWithEdit>(pComboBox, this, bTakeOwnership); 6749 ListBox* pListBox = dynamic_cast<ListBox*>(pWidget); 6750 return pListBox 6751 ? std::make_unique<SalInstanceComboBoxWithoutEdit>(pListBox, this, bTakeOwnership) 6752 : nullptr; 6753 } 6754 6755 std::unique_ptr<weld::EntryTreeView> 6756 SalInstanceBuilder::weld_entry_tree_view(const OString& containerid, const OString& entryid, 6757 const OString& treeviewid, bool bTakeOwnership) 6758 { 6759 vcl::Window* pContainer = m_xBuilder->get(containerid); 6760 return pContainer ? std::make_unique<SalInstanceEntryTreeView>( 6761 pContainer, this, bTakeOwnership, weld_entry(entryid, bTakeOwnership), 6762 weld_tree_view(treeviewid, bTakeOwnership)) 6763 : nullptr; 6764 } 6765 6766 std::unique_ptr<weld::TreeView> SalInstanceBuilder::weld_tree_view(const OString& id, 6767 bool bTakeOwnership) 6768 { 6769 SvTabListBox* pTreeView = m_xBuilder->get<SvTabListBox>(id); 6770 return pTreeView ? std::make_unique<SalInstanceTreeView>(pTreeView, this, bTakeOwnership) 6771 : nullptr; 6772 } 6773 6774 std::unique_ptr<weld::IconView> SalInstanceBuilder::weld_icon_view(const OString& id, 6775 bool bTakeOwnership) 6776 { 6777 IconView* pIconView = m_xBuilder->get<IconView>(id); 6778 return pIconView ? std::make_unique<SalInstanceIconView>(pIconView, this, bTakeOwnership) 6779 : nullptr; 6780 } 6781 6782 std::unique_ptr<weld::Label> SalInstanceBuilder::weld_label(const OString& id, bool bTakeOwnership) 6783 { 6784 Control* pLabel = m_xBuilder->get<Control>(id); 6785 return pLabel ? std::make_unique<SalInstanceLabel>(pLabel, this, bTakeOwnership) : nullptr; 6786 } 6787 6788 std::unique_ptr<weld::TextView> SalInstanceBuilder::weld_text_view(const OString& id, 6789 bool bTakeOwnership) 6790 { 6791 VclMultiLineEdit* pTextView = m_xBuilder->get<VclMultiLineEdit>(id); 6792 return pTextView ? std::make_unique<SalInstanceTextView>(pTextView, this, bTakeOwnership) 6793 : nullptr; 6794 } 6795 6796 std::unique_ptr<weld::Expander> SalInstanceBuilder::weld_expander(const OString& id, 6797 bool bTakeOwnership) 6798 { 6799 VclExpander* pExpander = m_xBuilder->get<VclExpander>(id); 6800 return pExpander ? std::make_unique<SalInstanceExpander>(pExpander, this, bTakeOwnership) 6801 : nullptr; 6802 } 6803 6804 std::unique_ptr<weld::DrawingArea> 6805 SalInstanceBuilder::weld_drawing_area(const OString& id, const a11yref& rA11yImpl, 6806 FactoryFunction pUITestFactoryFunction, void* pUserData, 6807 bool bTakeOwnership) 6808 { 6809 VclDrawingArea* pDrawingArea = m_xBuilder->get<VclDrawingArea>(id); 6810 return pDrawingArea ? std::make_unique<SalInstanceDrawingArea>(pDrawingArea, this, rA11yImpl, 6811 pUITestFactoryFunction, 6812 pUserData, bTakeOwnership) 6813 : nullptr; 6814 } 6815 6816 std::unique_ptr<weld::Menu> SalInstanceBuilder::weld_menu(const OString& id, bool bTakeOwnership) 6817 { 6818 PopupMenu* pMenu = m_xBuilder->get_menu(id); 6819 return pMenu ? std::make_unique<SalInstanceMenu>(pMenu, bTakeOwnership) : nullptr; 6820 } 6821 6822 std::unique_ptr<weld::Toolbar> SalInstanceBuilder::weld_toolbar(const OString& id, 6823 bool bTakeOwnership) 6824 { 6825 ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id); 6826 return pToolBox ? std::make_unique<SalInstanceToolbar>(pToolBox, this, bTakeOwnership) 6827 : nullptr; 6828 } 6829 6830 std::unique_ptr<weld::SizeGroup> SalInstanceBuilder::create_size_group() 6831 { 6832 return std::make_unique<SalInstanceSizeGroup>(); 6833 } 6834 6835 OString SalInstanceBuilder::get_current_page_help_id() const 6836 { 6837 TabControl* pCtrl = m_xBuilder->get<TabControl>("tabcontrol"); 6838 TabPage* pTabPage = pCtrl ? pCtrl->GetTabPage(pCtrl->GetCurPageId()) : nullptr; 6839 vcl::Window* pTabChild = pTabPage ? pTabPage->GetWindow(GetWindowType::FirstChild) : nullptr; 6840 pTabChild = pTabChild ? pTabChild->GetWindow(GetWindowType::FirstChild) : nullptr; 6841 if (pTabChild) 6842 return pTabChild->GetHelpId(); 6843 return OString(); 6844 } 6845 6846 SalInstanceBuilder::~SalInstanceBuilder() 6847 { 6848 if (VclBuilderContainer* pOwnedToplevel 6849 = dynamic_cast<VclBuilderContainer*>(m_aOwnedToplevel.get())) 6850 pOwnedToplevel->m_pUIBuilder = std::move(m_xBuilder); 6851 else 6852 m_xBuilder.reset(); 6853 m_aOwnedToplevel.disposeAndClear(); 6854 } 6855 6856 weld::Builder* SalInstance::CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, 6857 const OUString& rUIFile) 6858 { 6859 SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent); 6860 vcl::Window* pParentWidget = pParentInstance ? pParentInstance->getWidget() : nullptr; 6861 return new SalInstanceBuilder(pParentWidget, rUIRoot, rUIFile); 6862 } 6863 6864 weld::Builder* SalInstance::CreateInterimBuilder(vcl::Window* pParent, const OUString& rUIRoot, 6865 const OUString& rUIFile, bool, sal_uInt64) 6866 { 6867 return new SalInstanceBuilder(pParent, rUIRoot, rUIFile); 6868 } 6869 6870 void SalInstanceWindow::help() 6871 { 6872 //show help for widget with keyboard focus 6873 vcl::Window* pWidget = ImplGetSVData()->mpWinData->mpFocusWin; 6874 if (!pWidget) 6875 pWidget = m_xWindow; 6876 OString sHelpId = pWidget->GetHelpId(); 6877 while (sHelpId.isEmpty()) 6878 { 6879 pWidget = pWidget->GetParent(); 6880 if (!pWidget) 6881 break; 6882 sHelpId = pWidget->GetHelpId(); 6883 } 6884 std::unique_ptr<weld::Widget> xTemp( 6885 pWidget != m_xWindow ? new SalInstanceWidget(pWidget, m_pBuilder, false) : nullptr); 6886 weld::Widget* pSource = xTemp ? xTemp.get() : this; 6887 bool bRunNormalHelpRequest = !m_aHelpRequestHdl.IsSet() || m_aHelpRequestHdl.Call(*pSource); 6888 Help* pHelp = bRunNormalHelpRequest ? Application::GetHelp() : nullptr; 6889 if (!pHelp) 6890 return; 6891 6892 // tdf#126007, there's a nice fallback route for offline help where 6893 // the current page of a notebook will get checked when the help 6894 // button is pressed and there was no help for the dialog found. 6895 // 6896 // But for online help that route doesn't get taken, so bodge this here 6897 // by using the page help id if available and if the help button itself 6898 // was the original id 6899 if (m_pBuilder && sHelpId.endsWith("/help")) 6900 { 6901 OString sPageId = m_pBuilder->get_current_page_help_id(); 6902 if (!sPageId.isEmpty()) 6903 sHelpId = sPageId; 6904 else 6905 { 6906 // tdf#129068 likewise the help for the wrapping dialog is less 6907 // helpful than the help for the content area could be 6908 vcl::Window* pContentArea = nullptr; 6909 if (::Dialog* pDialog = dynamic_cast<::Dialog*>(m_xWindow.get())) 6910 pContentArea = pDialog->get_content_area(); 6911 if (pContentArea) 6912 { 6913 vcl::Window* pContentWidget = pContentArea->GetWindow(GetWindowType::LastChild); 6914 if (pContentWidget) 6915 sHelpId = pContentWidget->GetHelpId(); 6916 } 6917 } 6918 } 6919 pHelp->Start(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), pSource); 6920 } 6921 6922 //iterate upwards through the hierarchy from this widgets through its parents 6923 //calling func with their helpid until func returns true or we run out of parents 6924 void SalInstanceWidget::help_hierarchy_foreach(const std::function<bool(const OString&)>& func) 6925 { 6926 vcl::Window* pParent = m_xWidget; 6927 while ((pParent = pParent->GetParent())) 6928 { 6929 if (func(pParent->GetHelpId())) 6930 return; 6931 } 6932 } 6933 6934 weld::MessageDialog* SalInstance::CreateMessageDialog(weld::Widget* pParent, 6935 VclMessageType eMessageType, 6936 VclButtonsType eButtonsType, 6937 const OUString& rPrimaryMessage) 6938 { 6939 SalInstanceWidget* pParentInstance = dynamic_cast<SalInstanceWidget*>(pParent); 6940 SystemWindow* pParentWidget = pParentInstance ? pParentInstance->getSystemWindow() : nullptr; 6941 VclPtrInstance<MessageDialog> xMessageDialog(pParentWidget, rPrimaryMessage, eMessageType, 6942 eButtonsType); 6943 return new SalInstanceMessageDialog(xMessageDialog, nullptr, true); 6944 } 6945 6946 weld::Window* SalInstance::GetFrameWeld(const css::uno::Reference<css::awt::XWindow>& rWindow) 6947 { 6948 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper(); 6949 if (!pWrapper) 6950 return nullptr; 6951 VclPtr<vcl::Window> xWindow = pWrapper->GetWindow(rWindow); 6952 if (!xWindow) 6953 return nullptr; 6954 return xWindow->GetFrameWeld(); 6955 } 6956 6957 weld::Window* SalFrame::GetFrameWeld() const 6958 { 6959 if (!m_xFrameWeld) 6960 { 6961 vcl::Window* pWindow = GetWindow(); 6962 pWindow = pWindow ? pWindow->ImplGetWindow() : nullptr; 6963 assert(!pWindow || (pWindow->IsSystemWindow() || pWindow->IsDockingWindow())); 6964 if (pWindow) 6965 m_xFrameWeld.reset(new SalInstanceWindow(pWindow, nullptr, false)); 6966 } 6967 return m_xFrameWeld.get(); 6968 } 6969 6970 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 6971
