cui/uiconfig/ui/specialcharacters.ui | 423 ++------------------------ include/sfx2/charmapcontainer.hxx | 63 ++-- include/sfx2/charwin.hxx | 83 ----- sfx2/Library_sfx.mk | 1 sfx2/source/control/charmapcontainer.cxx | 359 +++++++++++++--------- sfx2/source/control/charmapcontrol.cxx | 4 sfx2/source/control/charwin.cxx | 253 ---------------- sfx2/uiconfig/ui/charmapcontrol.ui | 486 ++----------------------------- solenv/clang-format/excludelist | 1 solenv/sanitizers/ui/cui.suppr | 32 -- svx/source/dialog/cuicharmap.cxx | 5 vcl/inc/salvtables.hxx | 12 vcl/source/app/salvtables.cxx | 54 +-- 13 files changed, 372 insertions(+), 1404 deletions(-)
New commits: commit de23a47460ef3e1fb5ea08d87930cd66ac71ef4a Author: Michael Weghorn <[email protected]> AuthorDate: Sat Dec 20 23:05:35 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Sun Dec 21 01:37:17 2025 +0100 vcl weld: Deduplicate ItemView::get_{selected,cursor} impls The implementations for SalInstanceTreeView and SalInstanceIconView are the same. Deduplicate by moving logic to the SalInstanceItemView base class. Change-Id: Id507c84dab211980f31826b9f09efb58e61ad538 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196038 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 68c76810e6a2..63f780541594 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -1527,6 +1527,10 @@ public: virtual OUString get_selected_id() const override; virtual OUString get_selected_text() const override; + virtual bool get_selected(weld::TreeIter* pIter) const override; + + virtual bool get_cursor(weld::TreeIter* pIter) const override; + virtual int n_children() const override; private: @@ -1750,10 +1754,6 @@ public: virtual void copy_iterator(const weld::TreeIter& rSource, weld::TreeIter& rDest) const override; - virtual bool get_selected(weld::TreeIter* pIter) const override; - - virtual bool get_cursor(weld::TreeIter* pIter) const override; - bool get_iter_abs_pos(weld::TreeIter& rIter, int nPos) const; virtual bool iter_previous_sibling(weld::TreeIter& rIter) const override; @@ -1932,10 +1932,6 @@ public: virtual int count_selected_items() const override; - virtual bool get_selected(weld::TreeIter* pIter) const override; - - virtual bool get_cursor(weld::TreeIter* pIter) const override; - virtual void do_scroll_to_item(const weld::TreeIter& rIter) override; virtual void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) override; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 9b4c91a907c5..514b433c50d6 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -3593,6 +3593,24 @@ OUString SalInstanceItemView::get_selected_text() const return OUString(); } +bool SalInstanceItemView::get_selected(weld::TreeIter* pIter) const +{ + SvTreeListEntry* pEntry = m_pTreeListBox->FirstSelected(); + auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); + if (pVclIter) + pVclIter->iter = pEntry; + return pEntry != nullptr; +} + +bool SalInstanceItemView::get_cursor(weld::TreeIter* pIter) const +{ + SvTreeListEntry* pEntry = m_pTreeListBox->GetCurEntry(); + auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); + if (pVclIter) + pVclIter->iter = pEntry; + return pEntry != nullptr; +} + void SalInstanceItemView::do_select_all() { assert(m_pTreeListBox->IsUpdateMode() @@ -4567,24 +4585,6 @@ void SalInstanceTreeView::copy_iterator(const weld::TreeIter& rSource, weld::Tre rVclDest.iter = rVclSource.iter; } -bool SalInstanceTreeView::get_selected(weld::TreeIter* pIter) const -{ - SvTreeListEntry* pEntry = m_xTreeView->FirstSelected(); - auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); - if (pVclIter) - pVclIter->iter = pEntry; - return pEntry != nullptr; -} - -bool SalInstanceTreeView::get_cursor(weld::TreeIter* pIter) const -{ - SvTreeListEntry* pEntry = m_xTreeView->GetCurEntry(); - auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); - if (pVclIter) - pVclIter->iter = pEntry; - return pEntry != nullptr; -} - bool SalInstanceTreeView::get_iter_abs_pos(weld::TreeIter& rIter, int nAbsPos) const { SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter); @@ -5357,24 +5357,6 @@ void SalInstanceIconView::connect_get_image( int SalInstanceIconView::count_selected_items() const { return m_xIconView->GetSelectionCount(); } -bool SalInstanceIconView::get_selected(weld::TreeIter* pIter) const -{ - SvTreeListEntry* pEntry = m_xIconView->FirstSelected(); - auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); - if (pVclIter) - pVclIter->iter = pEntry; - return pEntry != nullptr; -} - -bool SalInstanceIconView::get_cursor(weld::TreeIter* pIter) const -{ - SvTreeListEntry* pEntry = m_xIconView->GetCurEntry(); - auto pVclIter = static_cast<SalInstanceTreeIter*>(pIter); - if (pVclIter) - pVclIter->iter = pEntry; - return pEntry != nullptr; -} - void SalInstanceIconView::do_scroll_to_item(const weld::TreeIter& rIter) { assert(m_xIconView->IsUpdateMode() commit 883c7fe1b50fe85c2a2026e0b098be0d57ec19a2 Author: Michael Weghorn <[email protected]> AuthorDate: Sat Dec 20 22:42:49 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Sun Dec 21 01:37:11 2025 +0100 tdf#168594 Move CharAndFont to charmapcontainer.hxx This was only in include/sfx2/charwin.hxx because it was used by SvxCharView also defined in that file before that one was dropped in previous commit Change-Id: Id6407b1c4b154bc7004723a0534141107a6939d4 Author: Michael Weghorn <[email protected]> Date: Sat Dec 20 22:25:15 2025 +0100 tdf#168594 tdf#119931 a11y special chars: Use IconView for recent/favorites Move it to the same header as the SfxCharmapContainer class where this is mainly used and drop the obsolete charwin.hxx. Change-Id: I5e31764d4a0d5bbed6f387b5b44bd93002b1b705 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196036 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/include/sfx2/charmapcontainer.hxx b/include/sfx2/charmapcontainer.hxx index 02a9e6104492..00aaf7f16b77 100644 --- a/include/sfx2/charmapcontainer.hxx +++ b/include/sfx2/charmapcontainer.hxx @@ -19,7 +19,6 @@ #pragma once -#include <sfx2/charwin.hxx> #include <sfx2/dllapi.h> #include <vcl/virdev.hxx> #include <vcl/weld/Builder.hxx> @@ -27,6 +26,20 @@ #include <vcl/weld/weld.hxx> #include <deque> +struct CharAndFont +{ + OUString sChar; + OUString sFont; + + CharAndFont(const OUString& rChar, const OUString& rFont) + : sChar(rChar) + , sFont(rFont) + { + } + + bool operator==(const CharAndFont& rOther) const = default; +}; + class SFX2_DLLPUBLIC SfxCharmapContainer { std::deque<CharAndFont> m_aRecentChars; diff --git a/include/sfx2/charwin.hxx b/include/sfx2/charwin.hxx deleted file mode 100644 index 60daa52940e9..000000000000 --- a/include/sfx2/charwin.hxx +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#pragma once - -#include <rtl/ustring.hxx> - -struct CharAndFont -{ - OUString sChar; - OUString sFont; - - CharAndFont(const OUString& rChar, const OUString& rFont) - : sChar(rChar) - , sFont(rFont) - { - } - - bool operator==(const CharAndFont& rOther) const = default; -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ commit c184cd984865a0406940b9f39ac1cd538b922e8f Author: Michael Weghorn <[email protected]> AuthorDate: Sat Dec 20 22:25:15 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Sun Dec 21 01:37:04 2025 +0100 tdf#168594 tdf#119931 a11y special chars: Use IconView for recent/favorites For the recently used and favorite characters in the special characters toolbar popup (triggered by the "Insert Special Characters" toolbar button) and the special characters dialog (triggered via "Insert" -> "Special Character..."), SfxCharmapContainer was so far using grids of the custom SvxCharView, with each SvxCharView displaying one character. Switch from those grids of custom controls to weld::IconView, one for the recent characters and one for the favorites. This ensures more standard/consistent interaction behavior, like being able to navigate between the characters in the IconView using the arrow keys (tdf#168594) and allows dropping quite some custom logic. Previous commits already reworked the logic/refactored involved code to make the port to weld::IconView easier. Some notes: 1) As described in more detail in previous commit commit 176f8acd7a993fc45ac7f027123270f80e4924ea Author: Michael Weghorn <[email protected]> Date: Fri Dec 19 19:52:45 2025 +0100 tdf#168594 Rework SvxCharView activation logic , the toolbar popup activates characters on single click while the dialog does not. The GtkIconView:activate-on-single-click [1] property is set accordingly in the .ui file for the popup, but not for the dialog. 2) The logic to draw the "icon" of a single character, now located in SfxCharmapContainer::CreateIcon, is based on the existing/previous logic from SvxCharView, previously spread across multiple methods there (SvxCharView::SetDrawingArea, SvxCharView::UpdateFont, SvxCharView::Paint, logic pretty much in that order still). 3) When an item view loses focus, selection is cleared, and it is restored when it receives focus again - see ItemViewFocusInHdl and ItemViewFocusOutHdl. This is because it is irrelevant what character was previously selected in one of those icon views while interacting with the other icon view or the bigger table of icons in the special characters dialog. (Still showing selection might be considered misleading.) 4) The switch to weld::IconView also addresses various of the gla11y warnings in the special characters dialog (related ticket: tdf#119931). 5) The previously used SvxCharView class is now unused, and therefore dropped. [1] https://docs.gtk.org/gtk3/property.IconView.activate-on-single-click.html Change-Id: Id6407b1c4b154bc7004723a0534141107a6939d4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196035 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/cui/uiconfig/ui/specialcharacters.ui b/cui/uiconfig/ui/specialcharacters.ui index bb0a05caefd6..9e6361eab17e 100644 --- a/cui/uiconfig/ui/specialcharacters.ui +++ b/cui/uiconfig/ui/specialcharacters.ui @@ -2,6 +2,26 @@ <!-- Generated with glade 3.40.0 --> <interface domain="cui"> <requires lib="gtk+" version="3.24"/> + <object class="GtkTreeStore" id="favchars_treestore"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name tooltip --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="recentchars_treestore"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name tooltip --> + <column type="gchararray"/> + </columns> + </object> <object class="GtkDialog" id="SpecialCharactersDialog"> <property name="can-focus">False</property> <property name="border-width">6</property> @@ -373,7 +393,7 @@ <property name="valign">start</property> <property name="label" translatable="yes" context="specialcharacters|symboltext1">Recent Characters:</property> <property name="use-underline">True</property> - <property name="mnemonic-widget">viewchar1</property> + <property name="mnemonic-widget">recentchars_iconview</property> </object> <packing> <property name="expand">False</property> @@ -382,202 +402,19 @@ </packing> </child> <child> - <object class="GtkBox" id="viewgrid"> + <object class="GtkIconView" id="recentchars_iconview"> <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkDrawingArea" id="viewchar1"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar2"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar3"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar4"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar5"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">4</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar6"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">5</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar7"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">6</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar8"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">7</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar9"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">8</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar10"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">9</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar11"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">10</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar12"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">11</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar13"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">12</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar14"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">13</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar15"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">14</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar16"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">15</property> - </packing> - </child> + <property name="can-focus">True</property> + <property name="halign">start</property> + <property name="valign">start</property> + <property name="margin">6</property> + <property name="model">recentchars_treestore</property> + <property name="pixbuf-column">0</property> + <property name="columns">16</property> + <property name="row-spacing">0</property> + <property name="column-spacing">0</property> + <property name="tooltip-column">2</property> + <property name="item-padding">2</property> </object> <packing> <property name="expand">False</property> @@ -607,7 +444,7 @@ <property name="valign">start</property> <property name="label" translatable="yes" context="specialcharacters|favbtn|symboltext2">Favorite Characters:</property> <property name="use-underline">True</property> - <property name="mnemonic-widget">favchar1</property> + <property name="mnemonic-widget">favchars_iconview</property> </object> <packing> <property name="expand">False</property> @@ -616,187 +453,19 @@ </packing> </child> <child> - <!-- n-columns=16 n-rows=1 --> - <object class="GtkGrid" id="favgrid"> + <object class="GtkIconView" id="favchars_iconview"> <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="column-spacing">2</property> - <child> - <object class="GtkDrawingArea" id="favchar1"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar2"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar4"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar3"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar5"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">4</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar6"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">5</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar7"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">6</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar8"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">7</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar16"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">15</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar15"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">14</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar14"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">13</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar13"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">12</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar12"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">11</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar11"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">10</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar10"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">9</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar9"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">8</property> - <property name="top-attach">0</property> - </packing> - </child> + <property name="can-focus">True</property> + <property name="halign">start</property> + <property name="valign">start</property> + <property name="margin">6</property> + <property name="model">favchars_treestore</property> + <property name="pixbuf-column">0</property> + <property name="columns">16</property> + <property name="row-spacing">0</property> + <property name="column-spacing">0</property> + <property name="tooltip-column">2</property> + <property name="item-padding">2</property> </object> <packing> <property name="expand">False</property> diff --git a/include/sfx2/charmapcontainer.hxx b/include/sfx2/charmapcontainer.hxx index 0c6ba5069f44..02a9e6104492 100644 --- a/include/sfx2/charmapcontainer.hxx +++ b/include/sfx2/charmapcontainer.hxx @@ -23,7 +23,7 @@ #include <sfx2/dllapi.h> #include <vcl/virdev.hxx> #include <vcl/weld/Builder.hxx> -#include <vcl/weld/customweld.hxx> +#include <vcl/weld/IconView.hxx> #include <vcl/weld/weld.hxx> #include <deque> @@ -32,43 +32,47 @@ class SFX2_DLLPUBLIC SfxCharmapContainer std::deque<CharAndFont> m_aRecentChars; std::deque<CharAndFont> m_aFavChars; - SvxCharView m_aRecentCharView[16]; - SvxCharView m_aFavCharView[16]; - std::unique_ptr<weld::CustomWeld> m_xRecentCharView[16]; - std::unique_ptr<weld::CustomWeld> m_xFavCharView[16]; + std::unique_ptr<weld::IconView> m_xRecentIconView; + std::unique_ptr<weld::IconView> m_xFavIconView; - std::unique_ptr<weld::Widget> m_xRecentGrid; - std::unique_ptr<weld::Widget> m_xFavGrid; + Link<const CharAndFont&, void> m_aCharActivateHdl; + Link<const CharAndFont&, void> m_aCharSelectedHdl; Link<void*, void> m_aUpdateFavHdl; Link<void*, void> m_aUpdateRecentHdl; - DECL_DLLPRIVATE_LINK(RecentContextMenuHdl, const CommandEvent&, void); - DECL_DLLPRIVATE_LINK(FavContextMenuHdl, const CommandEvent&, void); + DECL_DLLPRIVATE_LINK(IconViewSelectionChangedHdl, weld::IconView&, void); + DECL_DLLPRIVATE_LINK(ItemActivatedHdl, weld::IconView&, bool); + DECL_DLLPRIVATE_LINK(ItemViewFocusInHdl, weld::Widget&, void); + DECL_DLLPRIVATE_STATIC_LINK(SfxCharmapContainer, ItemViewFocusOutHdl, weld::Widget&, void); - DECL_DLLPRIVATE_LINK(RecentClearClickHdl, SvxCharView&, void); - DECL_DLLPRIVATE_LINK(FavClearClickHdl, SvxCharView&, void); - DECL_DLLPRIVATE_LINK(RecentClearAllClickHdl, SvxCharView&, void); - DECL_DLLPRIVATE_LINK(FavClearAllClickHdl, SvxCharView&, void); + DECL_DLLPRIVATE_LINK(RecentContextMenuHdl, const CommandEvent&, bool); + DECL_DLLPRIVATE_LINK(FavContextMenuHdl, const CommandEvent&, bool); - static void HandleContextMenu(std::span<SvxCharView> aCharViews, - const Link<SvxCharView&, void>& rClearHdl, - const Link<SvxCharView&, void>& rClearAllHdl, + DECL_DLLPRIVATE_LINK(RecentClearClickHdl, const CharAndFont&, void); + DECL_DLLPRIVATE_LINK(FavClearClickHdl, const CharAndFont&, void); + DECL_DLLPRIVATE_LINK(RecentClearAllClickHdl, weld::IconView&, void); + DECL_DLLPRIVATE_LINK(FavClearAllClickHdl, weld::IconView&, void); + + static bool HandleContextMenu(weld::IconView& rIconView, std::deque<CharAndFont>& rChars, + const Link<const CharAndFont&, void>& rClearHdl, + const Link<weld::IconView&, void>& rClearAllHdl, const CommandEvent& rCmdEvent); - static void updateCharControl(std::span<SvxCharView> aCharViews, - const std::deque<CharAndFont>& rChars); + static void updateCharControl(weld::IconView& rIconView, const std::deque<CharAndFont>& rChars); static bool GetDecimalValueAndCharName(std::u16string_view sCharText, sal_UCS4& rDecimalValue, OUString& rCharName); public: - SfxCharmapContainer(weld::Builder& rBuilder, const VclPtr<VirtualDevice>& rVirDev, - bool bLockGridSizes); + SfxCharmapContainer(weld::Builder& rBuilder); - void init(bool bActivateOnSingleClick, const Link<const CharAndFont&, void>& rActivateHdl, + void init(const Link<const CharAndFont&, void>& rActivateHdl, const Link<void*, void>& rUpdateFavHdl, const Link<void*, void>& rUpdateRecentHdl, - const Link<const CharAndFont&, void>& rFocusInHdl = Link<const CharAndFont&, void>()); + const Link<const CharAndFont&, void>& rCharSelectedHdl); + + static VclPtr<VirtualDevice> CreateIcon(weld::IconView& rIconView, const OUString& rFont, + const OUString& rText); void getFavCharacterList(); void updateFavCharControl(); diff --git a/include/sfx2/charwin.hxx b/include/sfx2/charwin.hxx index d5956a795f6d..60daa52940e9 100644 --- a/include/sfx2/charwin.hxx +++ b/include/sfx2/charwin.hxx @@ -19,10 +19,7 @@ #pragma once -#include <sfx2/dllapi.h> -#include <vcl/virdev.hxx> -#include <vcl/weld/customweld.hxx> -#include <vcl/weld/weld.hxx> +#include <rtl/ustring.hxx> struct CharAndFont { @@ -38,46 +35,4 @@ struct CharAndFont bool operator==(const CharAndFont& rOther) const = default; }; -class SAL_DLLPUBLIC_RTTI SvxCharView final : public weld::CustomWidgetController -{ -private: - VclPtr<VirtualDevice> mxVirDev; - vcl::Font maFont; - bool m_bActivateOnSingleClick; - OUString m_sText; - OUString m_sToolTip; - - Link<const CharAndFont&, void> maFocusInHdl; - Link<const CharAndFont&, void> maActivateHdl; - Link<const CommandEvent&, void> maContextMenuHdl; - - virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; - virtual void Resize() override; - virtual bool MouseButtonDown(const MouseEvent&) override; - virtual void GetFocus() override; - virtual void LoseFocus() override; - virtual OUString RequestHelp(tools::Rectangle&rHelpRect) override; - virtual bool KeyInput(const KeyEvent&) override; - virtual bool Command(const CommandEvent&) override; - virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; - -public: - SvxCharView(const VclPtr<VirtualDevice>& rVirDev); - SFX2_DLLPUBLIC virtual ~SvxCharView() override; - - void UpdateFont(const OUString& rFontFamilyName); - OUString GetFontFamilyName() const { return maFont.GetFamilyName(); } - void SetText( const OUString& rText ); - OUString const & GetText() const { return m_sText; } - CharAndFont GetCharAndFont() const; - void SetToolTip(const OUString& rToolTip) { m_sToolTip = rToolTip; }; - void SetActivateOnSingleClick(bool bActivate); - - Size get_preferred_size() const { return GetDrawingArea()->get_preferred_size(); } - - void setFocusInHdl(const Link<const CharAndFont&, void>& rLink); - void setActivateHdl(const Link<const CharAndFont&, void>& rLink); - void setContextMenuHdl(const Link<const CommandEvent&, void>& rLink); -}; - /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk index eb8617c7fc54..8357dec83af8 100644 --- a/sfx2/Library_sfx.mk +++ b/sfx2/Library_sfx.mk @@ -167,7 +167,6 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\ sfx2/source/control/thumbnailview \ sfx2/source/control/charmapcontainer \ sfx2/source/control/charmapcontrol \ - sfx2/source/control/charwin \ sfx2/source/control/unoctitm \ sfx2/source/devtools/DevelopmentToolChildWindow \ sfx2/source/devtools/DevelopmentToolDockingWindow \ diff --git a/sfx2/source/control/charmapcontainer.cxx b/sfx2/source/control/charmapcontainer.cxx index 7a521a5abc0a..7ae42a55dde5 100644 --- a/sfx2/source/control/charmapcontainer.cxx +++ b/sfx2/source/control/charmapcontainer.cxx @@ -28,94 +28,26 @@ #include <sfx2/strings.hrc> #include <sfx2/sfxresid.hxx> #include <vcl/commandevent.hxx> +#include <vcl/weld/weldutils.hxx> #include <unicode/uchar.h> #include <unicode/utypes.h> using namespace css; -SfxCharmapContainer::SfxCharmapContainer(weld::Builder& rBuilder, const VclPtr<VirtualDevice>& rVirDev, bool bLockGridSizes) - : m_aRecentCharView{SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev)} - , m_aFavCharView{SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev), - SvxCharView(rVirDev)} - , m_xRecentCharView{std::make_unique<weld::CustomWeld>(rBuilder, "viewchar1", m_aRecentCharView[0]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar2", m_aRecentCharView[1]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar3", m_aRecentCharView[2]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar4", m_aRecentCharView[3]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar5", m_aRecentCharView[4]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar6", m_aRecentCharView[5]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar7", m_aRecentCharView[6]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar8", m_aRecentCharView[7]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar9", m_aRecentCharView[8]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar10", m_aRecentCharView[9]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar11", m_aRecentCharView[10]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar12", m_aRecentCharView[11]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar13", m_aRecentCharView[12]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar14", m_aRecentCharView[13]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar15", m_aRecentCharView[14]), - std::make_unique<weld::CustomWeld>(rBuilder, "viewchar16", m_aRecentCharView[15])} - , m_xFavCharView{std::make_unique<weld::CustomWeld>(rBuilder, "favchar1", m_aFavCharView[0]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar2", m_aFavCharView[1]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar3", m_aFavCharView[2]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar4", m_aFavCharView[3]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar5", m_aFavCharView[4]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar6", m_aFavCharView[5]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar7", m_aFavCharView[6]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar8", m_aFavCharView[7]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar9", m_aFavCharView[8]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar10", m_aFavCharView[9]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar11", m_aFavCharView[10]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar12", m_aFavCharView[11]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar13", m_aFavCharView[12]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar14", m_aFavCharView[13]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar15", m_aFavCharView[14]), - std::make_unique<weld::CustomWeld>(rBuilder, "favchar16", m_aFavCharView[15])} - , m_xRecentGrid(rBuilder.weld_widget(u"viewgrid"_ustr)) - , m_xFavGrid(rBuilder.weld_widget(u"favgrid"_ustr)) +SfxCharmapContainer::SfxCharmapContainer(weld::Builder& rBuilder) + : m_xRecentIconView(rBuilder.weld_icon_view(u"recentchars_iconview"_ustr)) + , m_xFavIconView(rBuilder.weld_icon_view(u"favchars_iconview"_ustr)) { - if (bLockGridSizes) - { - //so things don't jump around if all the children are hidden - m_xRecentGrid->set_size_request(-1, m_aRecentCharView[0].get_preferred_size().Height()); - m_xFavGrid->set_size_request(-1, m_aFavCharView[0].get_preferred_size().Height()); - } } -void SfxCharmapContainer::init(bool bActivateOnSingleClick, - const Link<const CharAndFont&, void>& rActivateHdl, +void SfxCharmapContainer::init(const Link<const CharAndFont&, void>& rActivateHdl, const Link<void*, void>& rUpdateFavHdl, const Link<void*, void>& rUpdateRecentHdl, - const Link<const CharAndFont&, void>& rFocusInHdl) + const Link<const CharAndFont&, void>& rCharSelectedHdl) { + m_aCharActivateHdl = rActivateHdl; + m_aCharSelectedHdl = rCharSelectedHdl; m_aUpdateFavHdl = rUpdateFavHdl; m_aUpdateRecentHdl = rUpdateRecentHdl; @@ -124,18 +56,106 @@ void SfxCharmapContainer::init(bool bActivateOnSingleClick, getFavCharacterList(); updateFavCharControl(); - for(int i = 0; i < 16; i++) + m_xRecentIconView->connect_selection_changed(LINK(this, SfxCharmapContainer, IconViewSelectionChangedHdl)); + m_xRecentIconView->connect_item_activated(LINK(this, SfxCharmapContainer, ItemActivatedHdl)); + m_xRecentIconView->connect_focus_in(LINK(this, SfxCharmapContainer, ItemViewFocusInHdl)); + m_xRecentIconView->connect_focus_out(LINK(this, SfxCharmapContainer, ItemViewFocusOutHdl)); + m_xRecentIconView->connect_command(LINK(this, SfxCharmapContainer, RecentContextMenuHdl)); + + m_xFavIconView->connect_selection_changed(LINK(this, SfxCharmapContainer, IconViewSelectionChangedHdl)); + m_xFavIconView->connect_item_activated(LINK(this, SfxCharmapContainer, ItemActivatedHdl)); + m_xFavIconView->connect_focus_in(LINK(this, SfxCharmapContainer, ItemViewFocusInHdl)); + m_xFavIconView->connect_focus_out(LINK(this, SfxCharmapContainer, ItemViewFocusOutHdl)); + m_xFavIconView->connect_command(LINK(this, SfxCharmapContainer, FavContextMenuHdl)); +} + +VclPtr<VirtualDevice> SfxCharmapContainer::CreateIcon(weld::IconView& rIconView, + const OUString& rFont, const OUString& rText) +{ + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + vcl::Font aFont = rStyleSettings.GetLabelFont(); + Size aFontSize = aFont.GetFontSize(); + aFont.SetFontSize(Size(aFontSize.Width() * 2, aFontSize.Height() * 2)); + + VclPtr<VirtualDevice> pDev = rIconView.create_virtual_device(); + + Size aSize; + { + auto popIt = pDev->ScopedPush(PUSH_ALLFONT); + weld::SetPointFont(*pDev, aFont); + aSize = Size(pDev->approximate_digit_width() * 2, pDev->GetTextHeight()); + } + + tools::Long nWinHeight = aSize.Height(); + aFont.SetFamilyName(rFont); + aFont.SetWeight(WEIGHT_NORMAL); + aFont.SetAlignment(ALIGN_TOP); + aFont.SetFontSize(pDev->PixelToLogic(Size(0, nWinHeight / 2))); + aFont.SetTransparent(true); + + pDev->SetOutputSize(aSize); + pDev->SetFont(aFont); + + const Color aWindowTextColor(rStyleSettings.GetFieldTextColor()); + Color aFillColor(rStyleSettings.GetWindowColor()); + Color aTextColor(rStyleSettings.GetWindowTextColor()); + Color aShadowColor(rStyleSettings.GetShadowColor()); + + bool bGotBoundary = true; + tools::Rectangle aBoundRect; + + tools::Long nY = (nWinHeight - pDev->GetTextHeight()) / 2; + + for (tools::Long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 1) { - m_aRecentCharView[i].SetActivateOnSingleClick(bActivateOnSingleClick); - m_aRecentCharView[i].setFocusInHdl(rFocusInHdl); - m_aRecentCharView[i].setActivateHdl(rActivateHdl); - m_aRecentCharView[i].setContextMenuHdl( - LINK(this, SfxCharmapContainer, RecentContextMenuHdl)); - m_aFavCharView[i].SetActivateOnSingleClick(bActivateOnSingleClick); - m_aFavCharView[i].setFocusInHdl(rFocusInHdl); - m_aFavCharView[i].setActivateHdl(rActivateHdl); - m_aFavCharView[i].setContextMenuHdl(LINK(this, SfxCharmapContainer, FavContextMenuHdl)); + if (!pDev->GetTextBoundRect(aBoundRect, rText) || aBoundRect.IsEmpty()) + { + bGotBoundary = false; + break; + } + + tools::Long nTextWidth = aBoundRect.GetWidth(); + if (aSize.Width() > nTextWidth) + break; + vcl::Font aFont2(aFont); + aFontSize.setHeight(nFontHeight); + aFont2.SetFontSize(aFontSize); + pDev->SetFont(aFont2); + nY = (nWinHeight - pDev->GetTextHeight()) / 2; } + + Point aPoint(2, nY); + + if (!bGotBoundary) + aPoint.setX((aSize.Width() - pDev->GetTextWidth(rText)) / 2); + else + { + // adjust position + aBoundRect += aPoint; + + // vertical adjustment + int nYLDelta = aBoundRect.Top(); + int nYHDelta = aSize.Height() - aBoundRect.Bottom(); + if (nYLDelta <= 0) + aPoint.AdjustY(-(nYLDelta - 1)); + else if (nYHDelta <= 0) + aPoint.AdjustY(nYHDelta - 1); + + // centrally align glyph + aPoint.setX(-aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2); + } + + pDev->SetFillColor(aFillColor); + pDev->SetLineColor(aShadowColor); + pDev->DrawRect(tools::Rectangle(Point(0, 0), aSize)); + + pDev->SetTextColor(aWindowTextColor); + pDev->DrawText(aPoint, rText); + + pDev->SetFillColor(aFillColor); + pDev->SetTextColor(aTextColor); + + return pDev; } void SfxCharmapContainer::getFavCharacterList() @@ -155,7 +175,7 @@ void SfxCharmapContainer::getFavCharacterList() void SfxCharmapContainer::updateFavCharControl() { - updateCharControl(m_aFavCharView, m_aFavChars); + updateCharControl(*m_xFavIconView, m_aFavChars); m_aUpdateFavHdl.Call(nullptr); } @@ -177,12 +197,17 @@ void SfxCharmapContainer::getRecentCharacterList() void SfxCharmapContainer::GrabFocusToFirstFavorite() { - m_aFavCharView[0].GrabFocus(); + std::unique_ptr<weld::TreeIter> pIter = m_xFavIconView->make_iterator(); + if (m_xFavIconView->get_iter_first(*pIter)) + { + m_xFavIconView->select(*pIter); + m_xFavIconView->grab_focus(); + } } void SfxCharmapContainer::updateRecentCharControl() { - updateCharControl(m_aRecentCharView, m_aRecentChars); + updateCharControl(*m_xRecentIconView, m_aRecentChars); m_aUpdateRecentHdl.Call(nullptr); } @@ -276,84 +301,132 @@ bool SfxCharmapContainer::isFavChar(const OUString& rTitle, const OUString& rFon return std::ranges::find(m_aFavChars, CharAndFont(rTitle, rFont)) != m_aFavChars.end(); } -void SfxCharmapContainer::HandleContextMenu(std::span<SvxCharView> aCharViews, - const Link<SvxCharView&, void>& rClearHdl, - const Link<SvxCharView&, void>& rClearAllHdl, +bool SfxCharmapContainer::HandleContextMenu(weld::IconView& rIconView, + std::deque<CharAndFont>& rChars, + const Link<const CharAndFont&, void>& rClearHdl, + const Link<weld::IconView&, void>& rClearAllHdl, const CommandEvent& rCmdEvent) { - assert(rCmdEvent.GetCommand() == CommandEventId::ContextMenu); + if (rCmdEvent.GetCommand() != CommandEventId::ContextMenu) + return false; - for (SvxCharView& rView : aCharViews) + Point aPos; + std::unique_ptr<weld::TreeIter> pItem; + if (rCmdEvent.IsMouseEvent()) { - // the context menu is opened for the currently focused view - if (!rView.HasFocus()) - continue; - - weld::DrawingArea* pDrawingArea = rView.GetDrawingArea(); - std::unique_ptr<weld::Builder> xBuilder( - Application::CreateBuilder(pDrawingArea, u"sfx/ui/charviewmenu.ui"_ustr)); - std::unique_ptr<weld::Menu> xItemMenu(xBuilder->weld_menu(u"charviewmenu"_ustr)); - const OUString sMenuId = xItemMenu->popup_at_rect( - pDrawingArea, tools::Rectangle(rCmdEvent.GetMousePosPixel(), Size(1, 1))); - if (sMenuId == u"clearchar") - rClearHdl.Call(rView); - else if (sMenuId == u"clearallchar") - rClearAllHdl.Call(rView); - - rView.Invalidate(); - return; + aPos = rCmdEvent.GetMousePosPixel(); + pItem = rIconView.get_item_at_pos(aPos); + if (!pItem) + return false; + rIconView.select(*pItem); + } + else + { + pItem = rIconView.make_iterator(); + if (!rIconView.get_selected(pItem.get())) + return false; + aPos = rIconView.get_rect(*pItem).Center(); } + + std::unique_ptr<weld::Builder> xBuilder( + Application::CreateBuilder(&rIconView, u"sfx/ui/charviewmenu.ui"_ustr)); + std::unique_ptr<weld::Menu> xItemMenu(xBuilder->weld_menu(u"charviewmenu"_ustr)); + const OUString sMenuId + = xItemMenu->popup_at_rect(&rIconView, tools::Rectangle(aPos, Size(1, 1))); + if (sMenuId == u"clearchar") + rClearHdl.Call(rChars.at(rIconView.get_iter_index_in_parent(*pItem))); + else if (sMenuId == u"clearallchar") + rClearAllHdl.Call(rIconView); + + return true; } -void SfxCharmapContainer::updateCharControl(std::span<SvxCharView> aCharViews, +void SfxCharmapContainer::updateCharControl(weld::IconView& rIconView, const std::deque<CharAndFont>& rChars) { - assert(rChars.size() <= aCharViews.size()); + rIconView.clear(); int i = 0; for (auto it = rChars.begin(); it != rChars.end(); ++it, i++) { - aCharViews[i].SetText(it->sChar); - + const int nIndex = rIconView.n_children(); + const OUString* pNullIconName = nullptr; + rIconView.insert(nIndex, nullptr, nullptr, pNullIconName, nullptr); + ScopedVclPtr<VirtualDevice> pDev = CreateIcon(rIconView, it->sFont, it->sChar); + rIconView.set_image(nIndex, *pDev); OUString sAccName; if (GetDecimalValueAndCharName(it->sChar, o3tl::temporary(sal_UCS4()), sAccName)) - aCharViews[i].SetAccessibleName(sAccName); - else - aCharViews[i].SetAccessibleName(OUString()); - aCharViews[i].SetToolTip(GetCharInfoText(it->sChar)); - - aCharViews[i].UpdateFont(it->sFont); - aCharViews[i].Show(); + rIconView.set_item_accessible_name(nIndex, sAccName); + rIconView.set_item_tooltip_text(nIndex, GetCharInfoText(it->sChar)); } +} - for (; i < 16; i++) - { - aCharViews[i].SetText(OUString()); - aCharViews[i].SetAccessibleName(OUString()); - aCharViews[i].SetToolTip(OUString()); - aCharViews[i].Hide(); - } +IMPL_LINK(SfxCharmapContainer, IconViewSelectionChangedHdl, weld::IconView&, rIconView, void) +{ + std::unique_ptr<weld::TreeIter> pIter = rIconView.make_iterator(); + if (!rIconView.get_selected(pIter.get())) + return; + + const int nIndex = rIconView.get_iter_index_in_parent(*pIter); + if (&rIconView == m_xRecentIconView.get()) + m_aCharSelectedHdl.Call(m_aRecentChars.at(nIndex)); + else if (&rIconView == m_xFavIconView.get()) + m_aCharSelectedHdl.Call(m_aFavChars.at(nIndex)); } -IMPL_LINK(SfxCharmapContainer, RecentContextMenuHdl, const CommandEvent&, rCmdEvent, void) +IMPL_LINK(SfxCharmapContainer, ItemViewFocusInHdl, weld::Widget&, rWidget, void) { - HandleContextMenu(m_aRecentCharView, (LINK(this, SfxCharmapContainer, RecentClearClickHdl)), - LINK(this, SfxCharmapContainer, RecentClearAllClickHdl), rCmdEvent); + weld::IconView& rIconView = dynamic_cast<weld::IconView&>(rWidget); + std::unique_ptr<weld::TreeIter> pIter = rIconView.make_iterator(); + if (rIconView.get_cursor(pIter.get())) + rIconView.select(*pIter); + else if (rIconView.get_iter_first(*pIter)) + rIconView.select(*pIter); + else + return; + + IconViewSelectionChangedHdl(rIconView); +} + +IMPL_STATIC_LINK(SfxCharmapContainer, ItemViewFocusOutHdl, weld::Widget&, rWidget, void) +{ + weld::IconView& rIconView = dynamic_cast<weld::IconView&>(rWidget); + rIconView.unselect_all(); +} + +IMPL_LINK(SfxCharmapContainer, ItemActivatedHdl, weld::IconView&, rIconView, bool) +{ + std::unique_ptr<weld::TreeIter> pIter = rIconView.make_iterator(); + if (!rIconView.get_selected(pIter.get())) + return false; + + const int nIndex = rIconView.get_iter_index_in_parent(*pIter); + if (&rIconView == m_xRecentIconView.get()) + m_aCharActivateHdl.Call(m_aRecentChars.at(nIndex)); + else if (&rIconView == m_xFavIconView.get()) + m_aCharActivateHdl.Call(m_aFavChars.at(nIndex)); + + return true; } -IMPL_LINK(SfxCharmapContainer, FavContextMenuHdl, const CommandEvent&, rCmdEvent, void) +IMPL_LINK(SfxCharmapContainer, RecentContextMenuHdl, const CommandEvent&, rCmdEvent, bool) { - HandleContextMenu(m_aFavCharView, LINK(this, SfxCharmapContainer, FavClearClickHdl), - LINK(this, SfxCharmapContainer, FavClearAllClickHdl), rCmdEvent); + return HandleContextMenu(*m_xRecentIconView, m_aRecentChars, + LINK(this, SfxCharmapContainer, RecentClearClickHdl), + LINK(this, SfxCharmapContainer, RecentClearAllClickHdl), rCmdEvent); } -IMPL_LINK(SfxCharmapContainer, RecentClearClickHdl, SvxCharView&, rView, void) +IMPL_LINK(SfxCharmapContainer, FavContextMenuHdl, const CommandEvent&, rCmdEvent, bool) { - const OUString& sTitle = rView.GetText(); - OUString sFont = rView.GetFontFamilyName(); + return HandleContextMenu(*m_xFavIconView, m_aFavChars, + LINK(this, SfxCharmapContainer, FavClearClickHdl), + LINK(this, SfxCharmapContainer, FavClearAllClickHdl), rCmdEvent); +} +IMPL_LINK(SfxCharmapContainer, RecentClearClickHdl, const CharAndFont&, rCharAndFont, void) +{ // if recent char to be added is already in list, remove it - auto itChar = std::ranges::find(m_aRecentChars, CharAndFont(sTitle, sFont)); + auto itChar = std::ranges::find(m_aRecentChars, rCharAndFont); if (itChar != m_aRecentChars.end()) m_aRecentChars.erase(itChar); @@ -376,7 +449,7 @@ IMPL_LINK(SfxCharmapContainer, RecentClearClickHdl, SvxCharView&, rView, void) updateRecentCharControl(); } -IMPL_LINK_NOARG(SfxCharmapContainer, RecentClearAllClickHdl, SvxCharView&, void) +IMPL_LINK_NOARG(SfxCharmapContainer, RecentClearAllClickHdl, weld::IconView&, void) { m_aRecentChars.clear(); @@ -388,13 +461,13 @@ IMPL_LINK_NOARG(SfxCharmapContainer, RecentClearAllClickHdl, SvxCharView&, void) updateRecentCharControl(); } -IMPL_LINK(SfxCharmapContainer, FavClearClickHdl, SvxCharView&, rView, void) +IMPL_LINK(SfxCharmapContainer, FavClearClickHdl, const CharAndFont&, rChar, void) { - deleteFavCharacterFromList(rView.GetText(), rView.GetFontFamilyName()); + deleteFavCharacterFromList(rChar.sChar, rChar.sFont); updateFavCharControl(); } -IMPL_LINK_NOARG(SfxCharmapContainer, FavClearAllClickHdl, SvxCharView&, void) +IMPL_LINK_NOARG(SfxCharmapContainer, FavClearAllClickHdl, weld::IconView&, void) { m_aFavChars.clear(); diff --git a/sfx2/source/control/charmapcontrol.cxx b/sfx2/source/control/charmapcontrol.cxx index d4997ee55d54..35bf8e14a272 100644 --- a/sfx2/source/control/charmapcontrol.cxx +++ b/sfx2/source/control/charmapcontrol.cxx @@ -31,14 +31,14 @@ SfxCharmapCtrl::SfxCharmapCtrl(CharmapPopup* pControl, weld::Widget* pParent) : WeldToolbarPopup(pControl->getFrameInterface(), pParent, u"sfx/ui/charmapcontrol.ui"_ustr, u"charmapctrl"_ustr) , m_xControl(pControl) , m_xVirDev(VclPtr<VirtualDevice>::Create()) - , m_aCharmapContents(*m_xBuilder, m_xVirDev, false) + , m_aCharmapContents(*m_xBuilder) , m_xRecentLabel(m_xBuilder->weld_label(u"label2"_ustr)) , m_xDlgBtn(m_xBuilder->weld_button(u"specialchardlg"_ustr)) , m_xCharInfoLabel(m_xBuilder->weld_label(u"charinfolabel"_ustr)) { m_xCharInfoLabel->set_size_request(-1, m_xCharInfoLabel->get_text_height() * 2); - m_aCharmapContents.init(true, LINK(this, SfxCharmapCtrl, CharActivateHdl), + m_aCharmapContents.init(LINK(this, SfxCharmapCtrl, CharActivateHdl), Link<void*,void>(), LINK(this, SfxCharmapCtrl, UpdateRecentHdl), LINK(this, SfxCharmapCtrl, CharFocusInHdl)); diff --git a/sfx2/source/control/charwin.cxx b/sfx2/source/control/charwin.cxx deleted file mode 100644 index d4693f9e7e58..000000000000 --- a/sfx2/source/control/charwin.cxx +++ /dev/null @@ -1,253 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <vcl/settings.hxx> -#include <vcl/virdev.hxx> -#include <vcl/commandevent.hxx> -#include <vcl/event.hxx> -#include <vcl/svapp.hxx> -#include <vcl/weld/weldutils.hxx> -#include <sfx2/charwin.hxx> -#include <sfx2/charmapcontainer.hxx> - -#include <com/sun/star/beans/PropertyValue.hpp> - -using namespace com::sun::star; - -SvxCharView::SvxCharView(const VclPtr<VirtualDevice>& rVirDev) - : mxVirDev(rVirDev) - , m_bActivateOnSingleClick(false) -{ -} - -SvxCharView::~SvxCharView() {} - -void SvxCharView::SetDrawingArea(weld::DrawingArea* pDrawingArea) -{ - CustomWidgetController::SetDrawingArea(pDrawingArea); - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); - vcl::Font aFont = rStyleSettings.GetLabelFont(); - const Size aFontSize = aFont.GetFontSize(); - aFont.SetFontSize(Size(aFontSize.Width() * 2, aFontSize.Height() * 2)); - auto popIt = mxVirDev->ScopedPush(PUSH_ALLFONT); - weld::SetPointFont(*mxVirDev, aFont); - pDrawingArea->set_size_request(mxVirDev->approximate_digit_width() * 2, - mxVirDev->GetTextHeight()); -} - -void SvxCharView::GetFocus() -{ - Invalidate(); - if (maFocusInHdl.IsSet()) - maFocusInHdl.Call(CharAndFont(GetText(), GetFontFamilyName())); -} - -void SvxCharView::LoseFocus() { Invalidate(); } - -OUString SvxCharView::RequestHelp(tools::Rectangle& rHelpRect) -{ - // Gtk3 requires a rectangle be specified for the tooltip to display, X11 does not. - rHelpRect = tools::Rectangle(Point(), GetOutputSizePixel()); - return m_sToolTip; -} - -bool SvxCharView::MouseButtonDown(const MouseEvent& rMEvt) -{ - if (rMEvt.IsLeft()) - { - GrabFocus(); - Invalidate(); - if (rMEvt.GetClicks() == 2 || m_bActivateOnSingleClick) - maActivateHdl.Call(GetCharAndFont()); - return true; - } - - return CustomWidgetController::MouseButtonDown(rMEvt); -} - -bool SvxCharView::KeyInput(const KeyEvent& rKEvt) -{ - bool bRet = false; - vcl::KeyCode aCode = rKEvt.GetKeyCode(); - switch (aCode.GetCode()) - { - case KEY_SPACE: - case KEY_RETURN: - maActivateHdl.Call(GetCharAndFont()); - bRet = true; - break; - } - return bRet; -} - -bool SvxCharView::Command(const CommandEvent& rCommandEvent) -{ - if (rCommandEvent.GetCommand() == CommandEventId::ContextMenu) - { - GrabFocus(); - Invalidate(); - maContextMenuHdl.Call(rCommandEvent); - return true; - } - - return weld::CustomWidgetController::Command(rCommandEvent); -} - -void SvxCharView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) -{ - rRenderContext.SetFont(maFont); - - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); - const Color aWindowTextColor(rStyleSettings.GetFieldTextColor()); - Color aHighlightColor(rStyleSettings.GetHighlightColor()); - Color aHighlightTextColor(rStyleSettings.GetHighlightTextColor()); - Color aFillColor(rStyleSettings.GetWindowColor()); - Color aTextColor(rStyleSettings.GetWindowTextColor()); - Color aShadowColor(rStyleSettings.GetShadowColor()); - - const OUString aText = GetText(); - - Size aSize(GetOutputSizePixel()); - tools::Long nAvailWidth = aSize.Width(); - tools::Long nWinHeight = aSize.Height(); - - bool bGotBoundary = true; - bool bShrankFont = false; - vcl::Font aOrigFont(rRenderContext.GetFont()); - Size aFontSize(aOrigFont.GetFontSize()); - ::tools::Rectangle aBoundRect; - - mxVirDev->Push(PUSH_ALLFONT); - mxVirDev->SetFont(maFont); - tools::Long nY = (nWinHeight - mxVirDev->GetTextHeight()) / 2; - mxVirDev->Pop(); - - for (tools::Long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 1) - { - if (!rRenderContext.GetTextBoundRect(aBoundRect, aText) || aBoundRect.IsEmpty()) - { - bGotBoundary = false; - break; - } - - //only shrink in the single glyph large view mode - tools::Long nTextWidth = aBoundRect.GetWidth(); - if (nAvailWidth > nTextWidth) - break; - vcl::Font aFont(aOrigFont); - aFontSize.setHeight(nFontHeight); - aFont.SetFontSize(aFontSize); - rRenderContext.SetFont(aFont); - nY = (nWinHeight - rRenderContext.GetTextHeight()) / 2; - bShrankFont = true; - } - - Point aPoint(2, nY); - - if (!bGotBoundary) - aPoint.setX((aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2); - else - { - // adjust position - aBoundRect += aPoint; - - // vertical adjustment - int nYLDelta = aBoundRect.Top(); - int nYHDelta = aSize.Height() - aBoundRect.Bottom(); - if (nYLDelta <= 0) - aPoint.AdjustY(-(nYLDelta - 1)); - else if (nYHDelta <= 0) - aPoint.AdjustY(nYHDelta - 1); - - // centrally align glyph - aPoint.setX(-aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2); - } - - // tdf#111924 - don't lose focus on context menu - if (HasFocus() || HasChildFocus()) - { - rRenderContext.SetFillColor(aHighlightColor); - rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize)); - - rRenderContext.SetTextColor(aHighlightTextColor); - rRenderContext.DrawText(aPoint, aText); - } - else - { - rRenderContext.SetFillColor(aFillColor); - rRenderContext.SetLineColor(aShadowColor); - rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aSize)); - - rRenderContext.SetTextColor(aWindowTextColor); - rRenderContext.DrawText(aPoint, aText); - } - rRenderContext.SetFillColor(aFillColor); - rRenderContext.SetTextColor(aTextColor); - - if (bShrankFont) - rRenderContext.SetFont(aOrigFont); -} - -void SvxCharView::setFocusInHdl(const Link<const CharAndFont&, void>& rLink) -{ - maFocusInHdl = rLink; -} - -void SvxCharView::setActivateHdl(const Link<const CharAndFont&, void>& rLink) -{ - maActivateHdl = rLink; -} - -void SvxCharView::setContextMenuHdl(const Link<const CommandEvent&, void>& rLink) -{ - maContextMenuHdl = rLink; -} - -void SvxCharView::UpdateFont(const OUString& rFontFamilyName) -{ - tools::Long nWinHeight = GetOutputSizePixel().Height(); - maFont.SetFamilyName(rFontFamilyName); - maFont.SetWeight(WEIGHT_NORMAL); - maFont.SetAlignment(ALIGN_TOP); - maFont.SetFontSize(mxVirDev->PixelToLogic(Size(0, nWinHeight / 2))); - maFont.SetTransparent(true); - - Invalidate(); -} - -void SvxCharView::Resize() -{ - // force recalculation of size - UpdateFont(maFont.GetFamilyName()); -} - -void SvxCharView::SetText(const OUString& rText) -{ - m_sText = rText; - Invalidate(); -} - -CharAndFont SvxCharView::GetCharAndFont() const -{ - return CharAndFont(GetText(), GetFontFamilyName()); -} - -void SvxCharView::SetActivateOnSingleClick(bool bActivate) { m_bActivateOnSingleClick = bActivate; } - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sfx2/uiconfig/ui/charmapcontrol.ui b/sfx2/uiconfig/ui/charmapcontrol.ui index ad4b79441721..e5022de6f070 100644 --- a/sfx2/uiconfig/ui/charmapcontrol.ui +++ b/sfx2/uiconfig/ui/charmapcontrol.ui @@ -2,6 +2,26 @@ <!-- Generated with glade 3.40.0 --> <interface domain="sfx"> <requires lib="gtk+" version="3.24"/> + <object class="GtkTreeStore" id="favchars_treestore"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name tooltip --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="recentchars_treestore"> + <columns> + <!-- column-name pixbuf --> + <column type="GdkPixbuf"/> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name tooltip --> + <column type="gchararray"/> + </columns> + </object> <object class="GtkPopover" id="charmapctrl"> <property name="can-focus">False</property> <property name="no-show-all">True</property> @@ -26,227 +46,18 @@ </packing> </child> <child> - <!-- n-columns=6 n-rows=3 --> - <object class="GtkGrid" id="favgrid"> + <object class="GtkIconView" id="favchars_iconview"> <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="halign">start</property> - <property name="row-spacing">3</property> - <property name="column-spacing">3</property> - <child> - <object class="GtkDrawingArea" id="favchar1"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar2"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar4"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar3"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar5"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">4</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar6"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">5</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar7"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar8"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar9"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar10"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar11"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">4</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar12"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">5</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar13"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar14"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar15"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="favchar16"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> + <property name="can-focus">True</property> + <property name="margin">6</property> + <property name="model">favchars_treestore</property> + <property name="pixbuf-column">0</property> + <property name="columns">6</property> + <property name="row-spacing">0</property> + <property name="column-spacing">0</property> + <property name="tooltip-column">2</property> + <property name="item-padding">2</property> + <property name="activate-on-single-click">True</property> </object> <packing> <property name="expand">False</property> @@ -267,227 +78,18 @@ </packing> </child> <child> - <!-- n-columns=6 n-rows=3 --> - <object class="GtkGrid" id="viewgrid"> + <object class="GtkIconView" id="recentchars_iconview"> <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="halign">start</property> - <property name="row-spacing">3</property> - <property name="column-spacing">3</property> - <child> - <object class="GtkDrawingArea" id="viewchar1"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar2"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar4"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar3"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar5"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">4</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar6"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">5</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar16"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar15"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar14"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar13"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">2</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar12"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">5</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar11"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">4</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar10"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar9"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar8"> - <property name="width-request">35</property> - <property name="height-request">35</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <object class="GtkDrawingArea" id="viewchar7"> -e ... etc. - the rest is truncated
