diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-04-04 14:30:03 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-04-06 19:53:00 +0200 |
commit | 5c32ba63163d9556ff89782a8074924cdf9dc554 (patch) | |
tree | 66acbb3b4c298c9f0cbff75f9e36bf3d759b7a0f /vcl | |
parent | 6f31c63e35abef03e6f938bbddc8778b70a62d43 (diff) |
weld OTableSubscriptionPage
Change-Id: I55c23448480384c9a7d78cd55550bb4812ebde72
Reviewed-on: https://gerrit.libreoffice.org/70314
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/app/salvtables.cxx | 145 | ||||
-rw-r--r-- | vcl/source/treelist/svlbitm.cxx | 28 | ||||
-rw-r--r-- | vcl/source/treelist/treelistbox.cxx | 27 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 116 |
4 files changed, 267 insertions, 49 deletions
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 5b60f02d47d4..361b8d7830a7 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -51,6 +51,7 @@ #include <vcl/ptrstyle.hxx> #include <vcl/slider.hxx> #include <vcl/sysdata.hxx> +#include <vcl/svimpbox.hxx> #include <vcl/svlbitm.hxx> #include <vcl/svtabbx.hxx> #include <vcl/tabctrl.hxx> @@ -2265,9 +2266,44 @@ struct SalInstanceTreeIter : public weld::TreeIter : iter(pOrig ? pOrig->iter : nullptr) { } + virtual bool equal(const TreeIter& rOther) const override + { + return iter == static_cast<const SalInstanceTreeIter&>(rOther).iter; + } SvTreeListEntry* iter; }; +namespace +{ + TriState get_toggle(SvTreeListEntry* pEntry, int col) + { + ++col; //skip dummy/expander column + + if (static_cast<size_t>(col) == pEntry->ItemCount()) + return TRISTATE_FALSE; + + assert(col >= 0 && static_cast<size_t>(col) < pEntry->ItemCount()); + SvLBoxItem& rItem = pEntry->GetItem(col); + assert(dynamic_cast<SvLBoxButton*>(&rItem)); + SvLBoxButton& rToggle = static_cast<SvLBoxButton&>(rItem); + if (rToggle.IsStateTristate()) + return TRISTATE_INDET; + else if (rToggle.IsStateChecked()) + return TRISTATE_TRUE; + return TRISTATE_FALSE; + } + + bool get_text_emphasis(SvTreeListEntry* pEntry, int col) + { + ++col; //skip dummy/expander column + + assert(col >= 0 && static_cast<size_t>(col) < pEntry->ItemCount()); + SvLBoxItem& rItem = pEntry->GetItem(col); + assert(dynamic_cast<SvLBoxString*>(&rItem)); + return static_cast<SvLBoxString&>(rItem).IsEmphasized(); + } +} + class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::TreeView { private: @@ -2276,6 +2312,7 @@ private: VclPtr<SvTabListBox> m_xTreeView; SvLBoxButtonData m_aCheckButtonData; SvLBoxButtonData m_aRadioButtonData; + bool m_bDisableCheckBoxAutoWidth; int m_nSortColumn; DECL_LINK(SelectHdl, SvTreeListBox*, void); @@ -2294,6 +2331,7 @@ public: , m_xTreeView(pTreeView) , m_aCheckButtonData(pTreeView, false) , m_aRadioButtonData(pTreeView, true) + , m_bDisableCheckBoxAutoWidth(false) , m_nSortColumn(-1) { m_xTreeView->SetNodeDefaultImages(); @@ -2338,6 +2376,7 @@ public: virtual void set_column_fixed_widths(const std::vector<int>& rWidths) override { + m_bDisableCheckBoxAutoWidth = true; std::vector<long> aTabPositions; aTabPositions.push_back(0); for (size_t i = 0; i < rWidths.size(); ++i) @@ -2670,25 +2709,20 @@ public: set_sensitive(pEntry, bSensitive, col); } - virtual bool get_toggle(int pos, int col) const override + virtual TriState get_toggle(int pos, int col) const override { SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); - - ++col; //skip dummy/expander column - - if (static_cast<size_t>(col) == pEntry->ItemCount()) - return false; - - assert(col >= 0 && static_cast<size_t>(col) < pEntry->ItemCount()); - SvLBoxItem& rItem = pEntry->GetItem(col); - assert(dynamic_cast<SvLBoxButton*>(&rItem)); - return static_cast<SvLBoxButton&>(rItem).IsStateChecked(); + return ::get_toggle(pEntry, col); } - virtual void set_toggle(int pos, bool bOn, int col) override + virtual TriState get_toggle(const weld::TreeIter& rIter, int col) const override { - SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + return ::get_toggle(rVclIter.iter, col); + } + void set_toggle(SvTreeListEntry* pEntry, TriState eState, int col) + { bool bRadio = std::find(m_aRadioIndexes.begin(), m_aRadioIndexes.end(), col) != m_aRadioIndexes.end(); ++col; //skip dummy/expander column @@ -2698,23 +2732,86 @@ public: if (static_cast<size_t>(col) == pEntry->ItemCount()) { - pEntry->AddItem(std::make_unique<SvLBoxButton>(SvLBoxButtonKind::EnabledCheckbox, - bRadio ? &m_aRadioButtonData : &m_aCheckButtonData)); + SvLBoxButtonData* pData = bRadio ? &m_aRadioButtonData : &m_aCheckButtonData; + + // if we want to have the implicit auto-sizing of the checkbox + // column we need to call EnableCheckButton and CheckBoxInserted to + // let it figure out that width. But we don't want to override any + // explicitly set column width, so disable this if we've set + // explicit column widths + if (!m_bDisableCheckBoxAutoWidth) + { + if (!(m_xTreeView->GetTreeFlags() & SvTreeFlags::CHKBTN)) + { + m_xTreeView->EnableCheckButton(pData); + // EnableCheckButton clobbered this, restore it + pData->SetLink(LINK(this, SalInstanceTreeView, ToggleHdl)); + } + } + + pEntry->AddItem(std::make_unique<SvLBoxButton>(SvLBoxButtonKind::EnabledCheckbox, pData)); SvViewDataEntry* pViewData = m_xTreeView->GetViewDataEntry(pEntry); m_xTreeView->InitViewData(pViewData, pEntry); + + if (!m_bDisableCheckBoxAutoWidth) + m_xTreeView->CheckBoxInserted(pEntry); } assert(col >= 0 && static_cast<size_t>(col) < pEntry->ItemCount()); SvLBoxItem& rItem = pEntry->GetItem(col); assert(dynamic_cast<SvLBoxButton*>(&rItem)); - if (bOn) - static_cast<SvLBoxButton&>(rItem).SetStateChecked(); - else - static_cast<SvLBoxButton&>(rItem).SetStateUnchecked(); + switch (eState) + { + case TRISTATE_TRUE: + static_cast<SvLBoxButton&>(rItem).SetStateChecked(); + break; + case TRISTATE_FALSE: + static_cast<SvLBoxButton&>(rItem).SetStateUnchecked(); + break; + case TRISTATE_INDET: + static_cast<SvLBoxButton&>(rItem).SetStateTristate(); + break; + } + + m_xTreeView->ModelHasEntryInvalidated(pEntry); + } + + virtual void set_toggle(int pos, TriState eState, int col) override + { + SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); + set_toggle(pEntry, eState, col); + } + + virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override + { + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + set_toggle(rVclIter.iter, eState, col); + } + + void set_text_emphasis(SvTreeListEntry* pEntry, bool bOn, int col) + { + ++col; //skip dummy/expander column + + assert(col >= 0 && static_cast<size_t>(col) < pEntry->ItemCount()); + SvLBoxItem& rItem = pEntry->GetItem(col); + assert(dynamic_cast<SvLBoxString*>(&rItem)); + static_cast<SvLBoxString&>(rItem).Emphasize(bOn); m_xTreeView->ModelHasEntryInvalidated(pEntry); } + virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override + { + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + set_text_emphasis(rVclIter.iter, bOn, col); + } + + virtual bool get_text_emphasis(const weld::TreeIter& rIter, int col) const override + { + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + return ::get_text_emphasis(rVclIter.iter, col); + } + void set_image(SvTreeListEntry* pEntry, const Image& rImage, int col) { if (col == -1) @@ -3244,7 +3341,15 @@ IMPL_LINK(SalInstanceTreeView, ToggleHdl, SvLBoxButtonData*, pData, void) // tdf#122874 Select the row, calling SelectHdl, before handling // the toggle - m_xTreeView->Select(pEntry, true); + if (!m_xTreeView->IsSelected(pEntry)) + { + m_xTreeView->SelectAll(false); + m_xTreeView->Select(pEntry, true); + } + + // toggled signal handlers can query get_cursor to get which + // node was clicked + m_xTreeView->pImpl->pCursor = pEntry; for (int i = 1, nCount = pEntry->ItemCount(); i < nCount; ++i) { diff --git a/vcl/source/treelist/svlbitm.cxx b/vcl/source/treelist/svlbitm.cxx index 76d67ff36b49..e7732f687d5b 100644 --- a/vcl/source/treelist/svlbitm.cxx +++ b/vcl/source/treelist/svlbitm.cxx @@ -173,11 +173,13 @@ bool SvLBoxButtonData::IsRadio() { SvLBoxString::SvLBoxString(const OUString& rStr) - : maText(rStr) + : mbEmphasized(false) + , maText(rStr) { } SvLBoxString::SvLBoxString() + : mbEmphasized(false) { } @@ -203,7 +205,19 @@ void SvLBoxString::Paint( nStyle |= DrawTextFlags::PathEllipsis | DrawTextFlags::Center; aSize.setWidth( rDev.GetEntryWidth() ); } + + if (mbEmphasized) + { + rRenderContext.Push(); + vcl::Font aFont(rRenderContext.GetFont()); + aFont.SetWeight(WEIGHT_BOLD); + rRenderContext.SetFont(aFont); + } + rRenderContext.DrawText(tools::Rectangle(rPos, aSize), maText, nStyle); + + if (mbEmphasized) + rRenderContext.Pop(); } std::unique_ptr<SvLBoxItem> SvLBoxString::Clone(SvLBoxItem const * pSource) const @@ -218,7 +232,19 @@ void SvLBoxString::InitViewData( { if( !pViewData ) pViewData = pView->GetViewDataItem( pEntry, this ); + + if (mbEmphasized) + { + pView->Push(); + vcl::Font aFont( pView->GetFont()); + aFont.SetWeight(WEIGHT_BOLD); + pView->Control::SetFont( aFont ); + } + pViewData->maSize = Size(pView->GetTextWidth(maText), pView->GetTextHeight()); + + if (mbEmphasized) + pView->Pop(); } // *************************************************************** diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx index 1a2bb1e9d65f..5bd2a6fb3d0b 100644 --- a/vcl/source/treelist/treelistbox.cxx +++ b/vcl/source/treelist/treelistbox.cxx @@ -1679,6 +1679,20 @@ void SvTreeListBox::SetCollapsedEntryBmp(SvTreeListEntry* pEntry,const Image& aB } } +void SvTreeListBox::CheckBoxInserted(SvTreeListEntry* pEntry) +{ + SvLBoxButton* pItem = static_cast<SvLBoxButton*>(pEntry->GetFirstItem(SvLBoxItemType::Button)); + if( pItem ) + { + long nWidth = pItem->GetSize(this, pEntry).Width(); + if( mnCheckboxItemWidth < nWidth ) + { + mnCheckboxItemWidth = nWidth; + nTreeFlags |= SvTreeFlags::RECALCTABS; + } + } +} + void SvTreeListBox::ImpEntryInserted( SvTreeListEntry* pEntry ) { @@ -1712,19 +1726,9 @@ void SvTreeListBox::ImpEntryInserted( SvTreeListEntry* pEntry ) if( !(nTreeFlags & SvTreeFlags::CHKBTN) ) return; - SvLBoxButton* pItem = static_cast<SvLBoxButton*>(pEntry->GetFirstItem(SvLBoxItemType::Button)); - if( pItem ) - { - long nWidth = pItem->GetSize(this, pEntry).Width(); - if( mnCheckboxItemWidth < nWidth ) - { - mnCheckboxItemWidth = nWidth; - nTreeFlags |= SvTreeFlags::RECALCTABS; - } - } + CheckBoxInserted(pEntry); } - void SvTreeListBox::SetCheckButtonState( SvTreeListEntry* pEntry, SvButtonState eState) { if( !(nTreeFlags & SvTreeFlags::CHKBTN) ) @@ -1846,7 +1850,6 @@ void SvTreeListBox::SetDefaultCollapsedEntryBmp( const Image& aBmp ) void SvTreeListBox::EnableCheckButton( SvLBoxButtonData* pData ) { - DBG_ASSERT(!GetEntryCount(),"EnableCheckButton: Entry count != 0"); if( !pData ) nTreeFlags &= ~SvTreeFlags::CHKBTN; else diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 853b2827bb07..06a2ba5a705c 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -5634,6 +5634,10 @@ struct GtkInstanceTreeIter : public weld::TreeIter else memset(&iter, 0, sizeof(iter)); } + virtual bool equal(const TreeIter& rOther) const override + { + return memcmp(&iter, &static_cast<const GtkInstanceTreeIter&>(rOther).iter, sizeof(GtkTreeIter)) == 0; + } GtkTreeIter iter; }; @@ -5647,6 +5651,10 @@ private: std::vector<gulong> m_aColumnSignalIds; // map from toggle column to toggle visibility column std::map<int, int> m_aToggleVisMap; + // map from toggle column to tristate column + std::map<int, int> m_aToggleTriStateMap; + // map from text column to text weight column + std::map<int, int> m_aWeightMap; std::vector<GtkSortType> m_aSavedSortTypes; std::vector<int> m_aSavedSortColumns; std::vector<int> m_aViewColToModelCol; @@ -5745,15 +5753,29 @@ private: return sRet; } + gint get_int(const GtkTreeIter& iter, int col) const + { + gint nRet(-1); + GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); + gtk_tree_model_get(pModel, const_cast<GtkTreeIter*>(&iter), col, &nRet, -1); + return nRet; + } + + bool get_bool(const GtkTreeIter& iter, int col) const + { + gboolean bRet(false); + GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); + gtk_tree_model_get(pModel, const_cast<GtkTreeIter*>(&iter), col, &bRet, -1); + return bRet; + } + bool get_bool(int pos, int col) const { gboolean bRet(false); GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) - { - gtk_tree_model_get(pModel, &iter, col, &bRet, -1); - } + bRet = get_bool(iter, col); return bRet; } @@ -5768,9 +5790,12 @@ private: GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) - { set(iter, col, rText); - } + } + + void set(const GtkTreeIter& iter, int col, bool bOn) + { + gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, bOn, -1); } void set(int pos, int col, bool bOn) @@ -5778,9 +5803,12 @@ private: GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) - { - gtk_tree_store_set(m_pTreeStore, &iter, col, bOn, -1); - } + set(iter, col, bOn); + } + + void set(const GtkTreeIter& iter, int col, gint bInt) + { + gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, bInt, -1); } static gboolean signalTestExpandRow(GtkTreeView*, GtkTreeIter* iter, GtkTreePath*, gpointer widget) @@ -5926,15 +5954,18 @@ public: for (GList* pRenderer = g_list_first(pRenderers); pRenderer; pRenderer = g_list_next(pRenderer)) { GtkCellRenderer* pCellRenderer = GTK_CELL_RENDERER(pRenderer->data); - if (m_nTextCol == -1 && GTK_IS_CELL_RENDERER_TEXT(pCellRenderer)) + if (GTK_IS_CELL_RENDERER_TEXT(pCellRenderer)) { - m_nTextCol = nIndex; + if (m_nTextCol == -1) + m_nTextCol = nIndex; + m_aWeightMap[nIndex] = -1; } else if (GTK_IS_CELL_RENDERER_TOGGLE(pCellRenderer)) { g_object_set_data(G_OBJECT(pCellRenderer), "g-lo-CellIndex", reinterpret_cast<gpointer>(nIndex)); g_signal_connect(G_OBJECT(pCellRenderer), "toggled", G_CALLBACK(signalCellToggled), this); m_aToggleVisMap[nIndex] = -1; + m_aToggleTriStateMap[nIndex] = -1; } else if (GTK_IS_CELL_RENDERER_PIXBUF(pCellRenderer)) { @@ -5950,11 +5981,15 @@ public: g_list_free(pRenderers); m_aViewColToModelCol.push_back(nIndex - 1); } + m_nIdCol = nIndex++; + for (auto& a : m_aToggleVisMap) - { a.second = nIndex++; - } + for (auto& a : m_aToggleTriStateMap) + a.second = nIndex++; + for (auto& a : m_aWeightMap) + a.second = nIndex++; GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); m_nRowDeletedSignalId = g_signal_connect(pModel, "row-deleted", G_CALLBACK(signalRowDeleted), this); @@ -6337,17 +6372,64 @@ public: set(pos, col, rText); } - virtual bool get_toggle(int pos, int col) const override + virtual TriState get_toggle(int pos, int col) const override { - return get_bool(pos, get_model_col(col)); + col = get_model_col(col); + if (get_bool(pos, m_aToggleTriStateMap.find(col)->second)) + return TRISTATE_INDET; + return get_bool(pos, col) ? TRISTATE_TRUE : TRISTATE_FALSE; + } + + virtual TriState get_toggle(const weld::TreeIter& rIter, int col) const override + { + col = get_model_col(col); + const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); + if (get_bool(rGtkIter.iter, m_aToggleTriStateMap.find(col)->second)) + return TRISTATE_INDET; + return get_bool(rGtkIter.iter, col) ? TRISTATE_TRUE : TRISTATE_FALSE; } - virtual void set_toggle(int pos, bool bOn, int col) override + virtual void set_toggle(int pos, TriState eState, int col) override { col = get_model_col(col); // checkbuttons are invisible until toggled on or off set(pos, m_aToggleVisMap[col], true); - set(pos, col, bOn); + if (eState == TRISTATE_INDET) + set(pos, m_aToggleTriStateMap[col], true); + else + { + set(pos, m_aToggleTriStateMap[col], false); + set(pos, col, eState == TRISTATE_TRUE); + } + } + + virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override + { + const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); + col = get_model_col(col); + // checkbuttons are invisible until toggled on or off + set(rGtkIter.iter, m_aToggleVisMap[col], true); + if (eState == TRISTATE_INDET) + set(rGtkIter.iter, m_aToggleTriStateMap[col], true); + else + { + set(rGtkIter.iter, m_aToggleTriStateMap[col], false); + set(rGtkIter.iter, col, eState == TRISTATE_TRUE); + } + } + + virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override + { + const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); + col = get_model_col(col); + set(rGtkIter.iter, m_aWeightMap[col], bOn ? PANGO_WEIGHT_BOLD : -1); + } + + virtual bool get_text_emphasis(const weld::TreeIter& rIter, int col) const override + { + const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); + col = get_model_col(col); + return get_int(rGtkIter.iter, m_aWeightMap.find(col)->second) == PANGO_WEIGHT_BOLD; } using GtkInstanceWidget::set_sensitive; @@ -6360,6 +6442,8 @@ public: col = get_model_col(col); col += m_nIdCol + 1; // skip over id column col += m_aToggleVisMap.size(); // skip over toggle columns + col += m_aToggleTriStateMap.size(); // skip over tristate columns + col += m_aWeightMap.size(); // skip over weight columns set(pos, col, bSensitive); } |