summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-01-18 17:08:58 +0000
committerCaolán McNamara <caolanm@redhat.com>2019-01-22 18:09:15 +0100
commitd01161d6ff82c61a73628f74eb57e60b843ae1a9 (patch)
tree925fed3f66ca8d1ad01d8afd8c0303bc56286bc8
parentResolves: tdf#122880 list of obj types at 0 height with gtk 3.18 (diff)
downloadcore-d01161d6ff82c61a73628f74eb57e60b843ae1a9.tar.gz
core-d01161d6ff82c61a73628f74eb57e60b843ae1a9.zip
Resolves: tdf#122484 replace gtk autocomplete with vcl-alike autoselect
Change-Id: I941e32a973cdd1bc79e3739b24fdf834aa52cb11 Reviewed-on: https://gerrit.libreoffice.org/66688 Tested-by: Jenkins Tested-by: Xisco Faulí <xiscofauli@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--basctl/uiconfig/basicide/ui/managebreakpoints.ui8
-rw-r--r--cui/uiconfig/ui/charnamepage.ui35
-rw-r--r--cui/uiconfig/ui/paratabspage.ui8
-rw-r--r--include/vcl/weld.hxx1
-rw-r--r--sfx2/uiconfig/ui/newstyle.ui8
-rw-r--r--starmath/uiconfig/smath/ui/fontdialog.ui8
-rw-r--r--vcl/source/app/salvtables.cxx3
-rw-r--r--vcl/source/window/builder.cxx28
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx245
9 files changed, 225 insertions, 119 deletions
diff --git a/basctl/uiconfig/basicide/ui/managebreakpoints.ui b/basctl/uiconfig/basicide/ui/managebreakpoints.ui
index 66cbb93aeb05..d02926ecb825 100644
--- a/basctl/uiconfig/basicide/ui/managebreakpoints.ui
+++ b/basctl/uiconfig/basicide/ui/managebreakpoints.ui
@@ -10,14 +10,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion1">
- <property name="model">liststore1</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkDialog" id="ManageBreakpointsDialog">
<property name="can_focus">False</property>
<property name="border_width">6</property>
diff --git a/cui/uiconfig/ui/charnamepage.ui b/cui/uiconfig/ui/charnamepage.ui
index 25cfe43b6e68..f96bfb050c9c 100644
--- a/cui/uiconfig/ui/charnamepage.ui
+++ b/cui/uiconfig/ui/charnamepage.ui
@@ -10,14 +10,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion1">
- <property name="model">liststore1</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkTreeStore" id="liststore2">
<columns>
<!-- column-name text -->
@@ -26,14 +18,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion2">
- <property name="model">liststore2</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkTreeStore" id="liststore3">
<columns>
<!-- column-name text -->
@@ -42,14 +26,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion3">
- <property name="model">liststore3</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkListStore" id="liststore4">
<columns>
<!-- column-name text -->
@@ -428,6 +404,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -558,6 +535,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -574,6 +552,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -590,6 +569,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -615,6 +595,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -766,6 +747,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -782,6 +764,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -798,6 +781,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -973,6 +957,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -989,6 +974,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
@@ -1005,6 +991,7 @@
<child internal-child="entry">
<object class="GtkEntry">
<property name="can_focus">True</property>
+ <property name="activates_default">True</property>
</object>
</child>
</object>
diff --git a/cui/uiconfig/ui/paratabspage.ui b/cui/uiconfig/ui/paratabspage.ui
index bedddbba6fe4..08125e6ad959 100644
--- a/cui/uiconfig/ui/paratabspage.ui
+++ b/cui/uiconfig/ui/paratabspage.ui
@@ -10,14 +10,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion1">
- <property name="model">liststore1</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">-56</property>
<property name="upper">56</property>
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 53bab37b6d78..15b705474505 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -885,6 +885,7 @@ public:
virtual int get_active() const override { return m_xTreeView->get_selected_index(); }
virtual void set_active(int pos) override
{
+ m_xTreeView->set_cursor(pos);
m_xTreeView->select(pos);
m_xEntry->set_text(m_xTreeView->get_selected_text());
}
diff --git a/sfx2/uiconfig/ui/newstyle.ui b/sfx2/uiconfig/ui/newstyle.ui
index 9761b0047d7c..af9b7e14716f 100644
--- a/sfx2/uiconfig/ui/newstyle.ui
+++ b/sfx2/uiconfig/ui/newstyle.ui
@@ -10,14 +10,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion1">
- <property name="model">liststore1</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkDialog" id="CreateStyleDialog">
<property name="can_focus">False</property>
<property name="border_width">6</property>
diff --git a/starmath/uiconfig/smath/ui/fontdialog.ui b/starmath/uiconfig/smath/ui/fontdialog.ui
index d57b8e0d72cd..b9530b00c728 100644
--- a/starmath/uiconfig/smath/ui/fontdialog.ui
+++ b/starmath/uiconfig/smath/ui/fontdialog.ui
@@ -10,14 +10,6 @@
<column type="gchararray"/>
</columns>
</object>
- <object class="GtkEntryCompletion" id="entrycompletion1">
- <property name="model">liststore1</property>
- <property name="text_column">0</property>
- <property name="inline_completion">True</property>
- <property name="popup_completion">False</property>
- <property name="popup_set_width">False</property>
- <property name="popup_single_match">False</property>
- </object>
<object class="GtkDialog" id="FontDialog">
<property name="can_focus">False</property>
<property name="border_width">6</property>
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index c62230b079ed..94260c2ddbf6 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -2035,6 +2035,7 @@ public:
{
SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
m_xTreeView->Select(pEntry, true);
+ m_xTreeView->MakeVisible(pEntry);
}
enable_notify_events();
}
@@ -3418,6 +3419,8 @@ IMPL_LINK(SalInstanceEntryTreeView, AutocompleteHdl, Edit&, rEdit, void)
}
}
+ m_xTreeView->select(nPos);
+
if (nPos != -1)
{
OUString aText = m_xTreeView->get_text(nPos);
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 7f9e0fcec4d4..287200e24986 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -374,34 +374,8 @@ namespace weld
m_aChangeHdl.Call(*this);
}
- void EntryTreeView::EntryModifyHdl(weld::Entry& rBox)
+ IMPL_LINK_NOARG(EntryTreeView, ModifyHdl, weld::Entry&, void)
{
- OUString sText(rBox.get_text());
- int nExists = m_xTreeView->find_text(sText);
- if (nExists != -1)
- {
- m_xTreeView->select(nExists);
- return;
- }
-
- m_xTreeView->select(-1);
- if (sText.isEmpty())
- return;
-
- int nCount = m_xTreeView->n_children();
- for (int i = 0; i < nCount; ++i)
- {
- if (m_xTreeView->get_text(i).startsWith(sText))
- {
- m_xTreeView->select(i);
- break;
- }
- }
- }
-
- IMPL_LINK(EntryTreeView, ModifyHdl, weld::Entry&, rBox, void)
- {
- EntryModifyHdl(rBox);
m_aChangeHdl.Call(*this);
}
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 83794ade2efd..167a10d1fe17 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -36,6 +36,7 @@
#include <tools/stream.hxx>
#include <unotools/resmgr.hxx>
#include <vcl/ImageTree.hxx>
+#include <vcl/i18nhelp.hxx>
#include <vcl/quickselectionengine.hxx>
#include <vcl/mnemonic.hxx>
#include <vcl/syswin.hxx>
@@ -218,7 +219,7 @@ public:
OUString aStr;
gchar *pText = gtk_clipboard_wait_for_text(clipboard);
if (pText)
- aStr = OUString(pText, rtl_str_getLength(pText), RTL_TEXTENCODING_UTF8);
+ aStr = OUString(pText, strlen(pText), RTL_TEXTENCODING_UTF8);
g_free(pText);
css::uno::Any aRet;
aRet <<= aStr.replaceAll("\r\n", "\n");
@@ -4740,6 +4741,29 @@ namespace
g_free(pName2);
return ret;
}
+
+ int starts_with(GtkTreeModel* pTreeModel, const OUString& rStr, int col, int nStartRow)
+ {
+ GtkTreeIter iter;
+ if (!gtk_tree_model_iter_nth_child(pTreeModel, &iter, nullptr, nStartRow))
+ return -1;
+
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+ int nRet = nStartRow;
+ do
+ {
+ gchar* pStr;
+ gtk_tree_model_get(pTreeModel, &iter, col, &pStr, -1);
+ OUString aStr(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
+ g_free(pStr);
+ const bool bMatch = rI18nHelper.MatchString(rStr, aStr);
+ if (bMatch)
+ return nRet;
+ ++nRet;
+ } while (gtk_tree_model_iter_next(pTreeModel, &iter));
+
+ return -1;
+ }
}
struct GtkInstanceTreeIter : public weld::TreeIter
@@ -5587,6 +5611,11 @@ public:
return gtk_tree_selection_count_selected_rows(gtk_tree_view_get_selection(m_pTreeView));
}
+ int starts_with(const OUString& rStr, int col, int nStartRow)
+ {
+ return ::starts_with(GTK_TREE_MODEL(m_pTreeStore), rStr, col, nStartRow);
+ }
+
virtual void disable_notify_events() override
{
g_signal_handler_block(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId);
@@ -6365,11 +6394,56 @@ private:
vcl::QuickSelectionEngine m_aQuickSelectionEngine;
std::vector<int> m_aSeparatorRows;
gboolean m_bPopupActive;
+ bool m_bAutoComplete;
gulong m_nChangedSignalId;
gulong m_nPopupShownSignalId;
gulong m_nKeyPressEventSignalId;
gulong m_nEntryInsertTextSignalId;
gulong m_nEntryActivateSignalId;
+ gulong m_nEntryFocusOutSignalId;
+ guint m_nAutoCompleteIdleId;
+
+ static gboolean idleAutoComplete(gpointer widget)
+ {
+ GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
+ pThis->auto_complete();
+ return false;
+ }
+
+ void auto_complete()
+ {
+ m_nAutoCompleteIdleId = 0;
+ OUString aStartText = get_active_text();
+ int nStartPos, nEndPos;
+ get_entry_selection_bounds(nStartPos, nEndPos);
+ int nMaxSelection = std::max(nStartPos, nEndPos);
+ if (nMaxSelection != aStartText.getLength())
+ return;
+
+ disable_notify_events();
+ int nActive = get_active();
+ int nStart = nActive;
+
+ if (nStart == -1)
+ nStart = 0;
+
+ // Try match case insensitive from current position
+ int nPos = starts_with(m_pTreeModel, aStartText, 0, nStart);
+ if (nPos == -1 && nStart != 0)
+ {
+ // Try match case insensitive, but from start
+ nPos = starts_with(m_pTreeModel, aStartText, 0, 0);
+ }
+
+ if (nPos != -1)
+ {
+ OUString aText = get_text(nPos);
+ if (aText != aStartText)
+ set_active_text(aText);
+ select_entry_region(aText.getLength(), aStartText.getLength());
+ }
+ enable_notify_events();
+ }
static void signalEntryInsertText(GtkEntry* pEntry, const gchar* pNewText, gint nNewTextLength,
gint* position, gpointer widget)
@@ -6381,18 +6455,27 @@ private:
void signal_entry_insert_text(GtkEntry* pEntry, const gchar* pNewText, gint nNewTextLength, gint* position)
{
- if (!m_aEntryInsertTextHdl.IsSet())
- return;
- OUString sText(pNewText, nNewTextLength, RTL_TEXTENCODING_UTF8);
- const bool bContinue = m_aEntryInsertTextHdl.Call(sText);
- if (bContinue && !sText.isEmpty())
+ // first filter inserted text
+ if (m_aEntryInsertTextHdl.IsSet())
{
- OString sFinalText(OUStringToOString(sText, RTL_TEXTENCODING_UTF8));
- g_signal_handlers_block_by_func(pEntry, gpointer(signalEntryInsertText), this);
- gtk_editable_insert_text(GTK_EDITABLE(pEntry), sFinalText.getStr(), sFinalText.getLength(), position);
- g_signal_handlers_unblock_by_func(pEntry, gpointer(signalEntryInsertText), this);
+ OUString sText(pNewText, nNewTextLength, RTL_TEXTENCODING_UTF8);
+ const bool bContinue = m_aEntryInsertTextHdl.Call(sText);
+ if (bContinue && !sText.isEmpty())
+ {
+ OString sFinalText(OUStringToOString(sText, RTL_TEXTENCODING_UTF8));
+ g_signal_handlers_block_by_func(pEntry, gpointer(signalEntryInsertText), this);
+ gtk_editable_insert_text(GTK_EDITABLE(pEntry), sFinalText.getStr(), sFinalText.getLength(), position);
+ g_signal_handlers_unblock_by_func(pEntry, gpointer(signalEntryInsertText), this);
+ }
+ g_signal_stop_emission_by_name(pEntry, "insert-text");
+ }
+ if (m_bAutoComplete)
+ {
+ // now check for autocompletes
+ if (m_nAutoCompleteIdleId)
+ g_source_remove(m_nAutoCompleteIdleId);
+ m_nAutoCompleteIdleId = g_idle_add(idleAutoComplete, this);
}
- g_signal_stop_emission_by_name(pEntry, "insert-text");
}
static void signalChanged(GtkComboBox*, gpointer widget)
@@ -6422,7 +6505,26 @@ private:
}
}
- static void signalEntryActivate(GtkComboBox*, gpointer widget)
+ static void signalEntryFocusOut(GtkWidget*, GdkEvent*, gpointer widget)
+ {
+ GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
+ pThis->signal_entry_focus_out();
+ }
+
+ void signal_entry_focus_out()
+ {
+ // if we have an untidy selection on losing focus remove the selection
+ int nStartPos, nEndPos;
+ if (get_entry_selection_bounds(nStartPos, nEndPos))
+ {
+ int nMin = std::min(nStartPos, nEndPos);
+ int nMax = std::max(nStartPos, nEndPos);
+ if (nMin != 0 || nMax != get_active_text().getLength())
+ select_entry_region(0, 0);
+ }
+ }
+
+ static void signalEntryActivate(GtkEntry*, gpointer widget)
{
GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
pThis->signal_entry_activate();
@@ -6492,20 +6594,6 @@ private:
return GTK_ENTRY(pChild);
}
- void setup_completion(GtkEntry* pEntry)
- {
- if (gtk_entry_get_completion(pEntry))
- return;
- GtkEntryCompletion* pCompletion = gtk_entry_completion_new();
- gtk_entry_completion_set_model(pCompletion, m_pTreeModel);
- gtk_entry_completion_set_text_column(pCompletion, 0);
- gtk_entry_completion_set_inline_selection(pCompletion, true);
- gtk_entry_completion_set_inline_completion(pCompletion, true);
- gtk_entry_completion_set_popup_completion(pCompletion, false);
- gtk_entry_set_completion(pEntry, pCompletion);
- g_object_unref(pCompletion);
- }
-
bool separator_function(int nIndex)
{
return std::find(m_aSeparatorRows.begin(), m_aSeparatorRows.end(), nIndex) != m_aSeparatorRows.end();
@@ -6665,8 +6753,10 @@ public:
, m_pMenu(nullptr)
, m_aQuickSelectionEngine(*this)
, m_bPopupActive(false)
+ , m_bAutoComplete(false)
, m_nChangedSignalId(g_signal_connect(m_pComboBox, "changed", G_CALLBACK(signalChanged), this))
, m_nPopupShownSignalId(g_signal_connect(m_pComboBox, "notify::popup-shown", G_CALLBACK(signalPopupShown), this))
+ , m_nAutoCompleteIdleId(0)
{
GList* cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(m_pComboBox));
if (!g_list_length(cells))
@@ -6691,15 +6781,17 @@ public:
if (GtkEntry* pEntry = get_entry())
{
- setup_completion(pEntry);
+ m_bAutoComplete = true;
m_nEntryInsertTextSignalId = g_signal_connect(pEntry, "insert-text", G_CALLBACK(signalEntryInsertText), this);
m_nEntryActivateSignalId = g_signal_connect(pEntry, "activate", G_CALLBACK(signalEntryActivate), this);
+ m_nEntryFocusOutSignalId = g_signal_connect(pEntry, "focus-out-event", G_CALLBACK(signalEntryFocusOut), this);
m_nKeyPressEventSignalId = 0;
}
else
{
m_nEntryInsertTextSignalId = 0;
m_nEntryActivateSignalId = 0;
+ m_nEntryFocusOutSignalId = 0;
m_nKeyPressEventSignalId = g_signal_connect(m_pWidget, "key-press-event", G_CALLBACK(signalKeyPress), this);
}
install_menu_typeahead();
@@ -6951,12 +7043,7 @@ public:
virtual void set_entry_completion(bool bEnable) override
{
- GtkEntry* pEntry = get_entry();
- assert(pEntry);
- if (bEnable)
- setup_completion(pEntry);
- else
- gtk_entry_set_completion(pEntry, nullptr);
+ m_bAutoComplete = bEnable;
}
virtual void disable_notify_events() override
@@ -6965,6 +7052,7 @@ public:
{
g_signal_handler_block(pEntry, m_nEntryInsertTextSignalId);
g_signal_handler_block(pEntry, m_nEntryActivateSignalId);
+ g_signal_handler_block(pEntry, m_nEntryFocusOutSignalId);
}
else
g_signal_handler_block(m_pComboBox, m_nKeyPressEventSignalId);
@@ -6981,6 +7069,7 @@ public:
if (GtkEntry* pEntry = get_entry())
{
g_signal_handler_unblock(pEntry, m_nEntryActivateSignalId);
+ g_signal_handler_unblock(pEntry, m_nEntryFocusOutSignalId);
g_signal_handler_unblock(pEntry, m_nEntryInsertTextSignalId);
}
else
@@ -7024,10 +7113,13 @@ public:
virtual ~GtkInstanceComboBox() override
{
+ if (m_nAutoCompleteIdleId)
+ g_source_remove(m_nAutoCompleteIdleId);
if (GtkEntry* pEntry = get_entry())
{
g_signal_handler_disconnect(pEntry, m_nEntryInsertTextSignalId);
g_signal_handler_disconnect(pEntry, m_nEntryActivateSignalId);
+ g_signal_handler_disconnect(pEntry, m_nEntryFocusOutSignalId);
}
else
g_signal_handler_disconnect(m_pComboBox, m_nKeyPressEventSignalId);
@@ -7042,6 +7134,8 @@ private:
GtkInstanceEntry* m_pEntry;
GtkInstanceTreeView* m_pTreeView;
gulong m_nKeyPressSignalId;
+ gulong m_nEntryInsertTextSignalId;
+ guint m_nAutoCompleteIdleId;
gboolean signal_key_press(GdkEventKey* pEvent)
{
@@ -7049,10 +7143,11 @@ private:
pEvent->keyval == GDK_KEY_KP_Down || pEvent->keyval == GDK_KEY_Down || pEvent->keyval == GDK_KEY_KP_Page_Down || pEvent->keyval == GDK_KEY_Page_Down)
{
gboolean ret;
- m_pTreeView->disable_notify_events();
+ disable_notify_events();
GtkWidget* pWidget = m_pTreeView->getWidget();
if (m_pTreeView->get_selected_index() == -1)
{
+ m_pTreeView->set_cursor(0);
m_pTreeView->select(0);
m_xEntry->set_text(m_xTreeView->get_selected_text());
}
@@ -7064,7 +7159,7 @@ private:
gtk_widget_grab_focus(m_pEntry->getWidget());
}
m_xEntry->select_region(0, -1);
- m_pTreeView->enable_notify_events();
+ enable_notify_events();
m_pEntry->fire_signal_changed();
return true;
}
@@ -7077,16 +7172,76 @@ private:
return pThis->signal_key_press(pEvent);
}
+ static gboolean idleAutoComplete(gpointer widget)
+ {
+ GtkInstanceEntryTreeView* pThis = static_cast<GtkInstanceEntryTreeView*>(widget);
+ pThis->auto_complete();
+ return false;
+ }
+
+ void auto_complete()
+ {
+ m_nAutoCompleteIdleId = 0;
+ OUString aStartText = get_active_text();
+ int nStartPos, nEndPos;
+ get_entry_selection_bounds(nStartPos, nEndPos);
+ int nMaxSelection = std::max(nStartPos, nEndPos);
+ if (nMaxSelection != aStartText.getLength())
+ return;
+
+ disable_notify_events();
+ int nActive = get_active();
+ int nStart = nActive;
+
+ if (nStart == -1)
+ nStart = 0;
+
+ // Try match case insensitive from current position
+ int nPos = m_pTreeView->starts_with(aStartText, 0, nStart);
+ if (nPos == -1 && nStart != 0)
+ {
+ // Try match case insensitive, but from start
+ nPos = m_pTreeView->starts_with(aStartText, 0, 0);
+ }
+
+ if (nPos != -1)
+ {
+ OUString aText = get_text(nPos);
+ if (aText != aStartText)
+ set_active_text(aText);
+ select_entry_region(aText.getLength(), aStartText.getLength());
+ }
+ enable_notify_events();
+ }
+
+ void signal_entry_insert_text(GtkEntry*, const gchar*, gint, gint*)
+ {
+ // now check for autocompletes
+ if (m_nAutoCompleteIdleId)
+ g_source_remove(m_nAutoCompleteIdleId);
+ m_nAutoCompleteIdleId = g_idle_add(idleAutoComplete, this);
+ }
+
+ static void signalEntryInsertText(GtkEntry* pEntry, const gchar* pNewText, gint nNewTextLength,
+ gint* position, gpointer widget)
+ {
+ GtkInstanceEntryTreeView* pThis = static_cast<GtkInstanceEntryTreeView*>(widget);
+ pThis->signal_entry_insert_text(pEntry, pNewText, nNewTextLength, position);
+ }
+
+
public:
GtkInstanceEntryTreeView(GtkContainer* pContainer, bool bTakeOwnership, std::unique_ptr<weld::Entry> xEntry, std::unique_ptr<weld::TreeView> xTreeView)
: EntryTreeView(std::move(xEntry), std::move(xTreeView))
, GtkInstanceContainer(pContainer, bTakeOwnership)
, m_pEntry(dynamic_cast<GtkInstanceEntry*>(m_xEntry.get()))
, m_pTreeView(dynamic_cast<GtkInstanceTreeView*>(m_xTreeView.get()))
+ , m_nAutoCompleteIdleId(0)
{
assert(m_pEntry);
GtkWidget* pWidget = m_pEntry->getWidget();
m_nKeyPressSignalId = g_signal_connect(pWidget, "key-press-event", G_CALLBACK(signalKeyPress), this);
+ m_nEntryInsertTextSignalId = g_signal_connect(pWidget, "insert-text", G_CALLBACK(signalEntryInsertText), this);
}
virtual void insert_separator(int /*pos*/) override
@@ -7105,7 +7260,6 @@ public:
virtual void set_entry_completion(bool bEnable) override
{
assert(!bEnable && "not implemented yet"); (void)bEnable;
- gtk_entry_set_completion(GTK_ENTRY(m_pEntry->getWidget()), nullptr);
}
virtual void grab_focus() override { m_xEntry->grab_focus(); }
@@ -7120,10 +7274,29 @@ public:
m_xEntry->connect_focus_out(rLink);
}
+ virtual void disable_notify_events() override
+ {
+ GtkWidget* pWidget = m_pEntry->getWidget();
+ g_signal_handler_block(pWidget, m_nEntryInsertTextSignalId);
+ g_signal_handler_block(pWidget, m_nKeyPressSignalId);
+ m_pTreeView->disable_notify_events();
+ GtkInstanceContainer::disable_notify_events();
+ }
+
+ virtual void enable_notify_events() override
+ {
+ GtkWidget* pWidget = m_pEntry->getWidget();
+ g_signal_handler_unblock(pWidget, m_nKeyPressSignalId);
+ g_signal_handler_unblock(pWidget, m_nEntryInsertTextSignalId);
+ m_pTreeView->enable_notify_events();
+ GtkInstanceContainer::disable_notify_events();
+ }
+
virtual ~GtkInstanceEntryTreeView() override
{
GtkWidget* pWidget = m_pEntry->getWidget();
g_signal_handler_disconnect(pWidget, m_nKeyPressSignalId);
+ g_signal_handler_disconnect(pWidget, m_nEntryInsertTextSignalId);
}
};