weld CodeCompleteWindow
Change-Id: Ibe620a42592761ee25d6329d26b1b1c452bdfd2b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89007
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/basctl/UIConfig_basicide.mk b/basctl/UIConfig_basicide.mk
index 9c87954..7593e5a 100644
--- a/basctl/UIConfig_basicide.mk
+++ b/basctl/UIConfig_basicide.mk
@@ -36,6 +36,7 @@ $(eval $(call gb_UIConfig_add_toolbarfiles,modules/BasicIDE,\
$(eval $(call gb_UIConfig_add_uifiles,modules/BasicIDE,\
basctl/uiconfig/basicide/ui/basicmacrodialog \
basctl/uiconfig/basicide/ui/breakpointmenus \
basctl/uiconfig/basicide/ui/codecomplete \
basctl/uiconfig/basicide/ui/combobox \
basctl/uiconfig/basicide/ui/defaultlanguage \
basctl/uiconfig/basicide/ui/deletelangdialog \
diff --git a/basctl/source/basicide/baside2.hxx b/basctl/source/basicide/baside2.hxx
index 0886234..0a476a7 100644
--- a/basctl/source/basicide/baside2.hxx
+++ b/basctl/source/basicide/baside2.hxx
@@ -26,7 +26,7 @@
#include <basic/sbmod.hxx>
#include <basic/sbstar.hxx>
#include <vcl/lstbox.hxx>
#include <sfx2/InterimItemWindow.hxx>
#include <vcl/idle.hxx>
#include <vcl/weld.hxx>
@@ -51,7 +51,6 @@ namespace basctl
{
class ObjectCatalog;
class CodeCompleteListBox;
class CodeCompleteWindow;
class ModulWindowLayout;
@@ -64,7 +63,7 @@ void setTextEngineText (ExtTextEngine&, OUString const&);
class EditorWindow final : public vcl::Window, public SfxListener
{
friend class CodeCompleteListBox;
friend class CodeCompleteWindow;
private:
class ChangesListener;
@@ -446,43 +445,25 @@ private:
} aSyntaxColors;
};
class CodeCompleteListBox: public ListBox
class CodeCompleteWindow final : public InterimItemWindow
{
friend class CodeCompleteWindow;
friend class EditorWindow;
private:
OUStringBuffer aFuncBuffer;
VclPtr<EditorWindow> pParent; // parent window
TextSelection m_aTextSelection;
std::unique_ptr<weld::TreeView> m_xListBox;
/* a buffer to build up function name when typing
* a function name, used for showing/hiding listbox values
* */
VclPtr<CodeCompleteWindow> pCodeCompleteWindow; // parent window
OUStringBuffer aFuncBuffer;
void InsertSelectedEntry(); // insert the selected entry
void SetMatchingEntries(); // sets the visible entries based on aFuncBuffer variable
void HideAndRestoreFocus();
TextView* GetParentEditView();
public:
explicit CodeCompleteListBox( CodeCompleteWindow* pPar );
virtual ~CodeCompleteListBox() override;
virtual void dispose() override;
void InsertSelectedEntry(); //insert the selected entry
DECL_LINK(ImplDoubleClickHdl, ListBox&, void);
DECL_LINK(ImplSelectHdl, ListBox&, void);
protected:
virtual void KeyInput( const KeyEvent& rKeyEvt ) override;
};
class CodeCompleteWindow: public vcl::Window
{
friend class CodeCompleteListBox;
private:
VclPtr<EditorWindow> pParent; // parent window
TextSelection aTextSelection;
VclPtr<CodeCompleteListBox> pListBox;
void InitListBox(); // initialize the ListBox
DECL_LINK(ImplDoubleClickHdl, weld::TreeView&, bool);
DECL_LINK(ImplSelectHdl, weld::TreeView&, void);
DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
public:
explicit CodeCompleteWindow( EditorWindow* pPar );
@@ -492,15 +473,18 @@ public:
void InsertEntry( const OUString& aStr );
void ClearListBox();
void SetTextSelection( const TextSelection& aSel );
const TextSelection& GetTextSelection() const { return aTextSelection;}
const TextSelection& GetTextSelection() const { return m_aTextSelection;}
void ResizeAndPositionListBox();
void SelectFirstEntry(); //selects first entry in ListBox
void ClearAndHide();
/*
* clears if typed anything, then hides
* the window, clear internal variables
* */
CodeCompleteListBox* GetListBox(){return pListBox;}
void ClearAndHide();
void HideAndRestoreFocus();
bool HandleKeyInput(const KeyEvent& rKeyEvt);
};
class UnoTypeCodeCompletetor
diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx
index 8f5888e..b8bdd56 100644
--- a/basctl/source/basicide/baside2b.cxx
+++ b/basctl/source/basicide/baside2b.cxx
@@ -458,9 +458,10 @@ void EditorWindow::MouseButtonDown( const MouseEvent &rEvt )
pEditView->MouseButtonDown( rEvt );
if( pCodeCompleteWnd->IsVisible() )
{
if( pEditView->GetSelection() != pCodeCompleteWnd->GetTextSelection() )
{//selection changed, code complete window should be hidden
pCodeCompleteWnd->GetListBox()->HideAndRestoreFocus();
if (pEditView->GetSelection() != pCodeCompleteWnd->GetTextSelection())
{
//selection changed, code complete window should be hidden
pCodeCompleteWnd->HideAndRestoreFocus();
}
}
}
@@ -518,13 +519,9 @@ void EditorWindow::KeyInput( const KeyEvent& rKEvt )
SfxViewShell *pVS( SfxViewShell::Current());
bool bDone = pVS && pVS->KeyInput( rKEvt );
if( pCodeCompleteWnd->IsVisible() && CodeCompleteOptions::IsCodeCompleteOn() )
if (pCodeCompleteWnd->IsVisible() && CodeCompleteOptions::IsCodeCompleteOn())
{
pCodeCompleteWnd->GetListBox()->KeyInput(rKEvt);
if( rKEvt.GetKeyCode().GetCode() == KEY_UP
|| rKEvt.GetKeyCode().GetCode() == KEY_DOWN
|| rKEvt.GetKeyCode().GetCode() == KEY_TAB
|| rKEvt.GetKeyCode().GetCode() == KEY_POINT)
if (pCodeCompleteWnd->HandleKeyInput(rKEvt))
return;
}
@@ -2519,78 +2516,72 @@ void WatchWindow::UpdateWatches(bool bBasicStopped)
setBasicWatchMode( false );
}
CodeCompleteListBox::CodeCompleteListBox( CodeCompleteWindow* pPar )
: ListBox(pPar, WB_SORT | WB_BORDER ),
pCodeCompleteWindow( pPar )
{
SetDoubleClickHdl(LINK(this, CodeCompleteListBox, ImplDoubleClickHdl));
SetSelectHdl(LINK(this, CodeCompleteListBox, ImplSelectHdl));
}
CodeCompleteListBox::~CodeCompleteListBox()
{
disposeOnce();
}
void CodeCompleteListBox::dispose()
{
pCodeCompleteWindow.clear();
ListBox::dispose();
}
IMPL_LINK_NOARG(CodeCompleteListBox, ImplDoubleClickHdl, ListBox&, void)
IMPL_LINK_NOARG(CodeCompleteWindow, ImplDoubleClickHdl, weld::TreeView&, bool)
{
InsertSelectedEntry();
return true;
}
IMPL_LINK_NOARG(CodeCompleteListBox, ImplSelectHdl, ListBox&, void)
{//give back the focus to the parent
pCodeCompleteWindow->pParent->GrabFocus();
}
TextView* CodeCompleteListBox::GetParentEditView()
IMPL_LINK_NOARG(CodeCompleteWindow, ImplSelectHdl, weld::TreeView&, void)
{
return pCodeCompleteWindow->pParent->GetEditView();
//give back the focus to the parent
pParent->GrabFocus();
}
void CodeCompleteListBox::InsertSelectedEntry()
TextView* CodeCompleteWindow::GetParentEditView()
{
return pParent->GetEditView();
}
void CodeCompleteWindow::InsertSelectedEntry()
{
OUString sSelectedEntry = m_xListBox->get_selected_text();
if( !aFuncBuffer.isEmpty() )
{
// if the user typed in something: remove, and insert
GetParentEditView()->SetSelection( pCodeCompleteWindow->pParent->GetLastHighlightPortionTextSelection() );
GetParentEditView()->SetSelection(pParent->GetLastHighlightPortionTextSelection());
GetParentEditView()->DeleteSelected();
if( !GetSelectedEntry().isEmpty() )
{//if the user selected something
GetParentEditView()->InsertText( GetSelectedEntry() );
if (!sSelectedEntry.isEmpty())
{
// if the user selected something
GetParentEditView()->InsertText(sSelectedEntry);
}
}
else
{
if( !GetSelectedEntry().isEmpty() )
{//if the user selected something
GetParentEditView()->InsertText( GetSelectedEntry() );
if (!sSelectedEntry.isEmpty())
{
// if the user selected something
GetParentEditView()->InsertText(sSelectedEntry);
}
}
HideAndRestoreFocus();
}
void CodeCompleteListBox::SetMatchingEntries()
void CodeCompleteWindow::SetMatchingEntries()
{
for(sal_Int32 i=0; i< GetEntryCount(); ++i)
for (sal_Int32 i = 0, nEntryCount = m_xListBox->n_children(); i< nEntryCount; ++i)
{
OUString sEntry = GetEntry(i);
if( sEntry.startsWithIgnoreAsciiCase( aFuncBuffer.toString() ) )
OUString sEntry = m_xListBox->get_text(i);
if (sEntry.startsWithIgnoreAsciiCase(aFuncBuffer.toString()))
{
SelectEntry(sEntry);
m_xListBox->select(i);
break;
}
}
}
void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
IMPL_LINK(CodeCompleteWindow, KeyInputHdl, const KeyEvent&, rKEvt, bool)
{
return HandleKeyInput(rKEvt);
}
bool CodeCompleteWindow::HandleKeyInput( const KeyEvent& rKeyEvt )
{
bool bHandled = true;
sal_Unicode aChar = rKeyEvt.GetKeyCode().GetCode();
if( (( aChar >= KEY_A ) && ( aChar <= KEY_Z ))
|| ((aChar >= KEY_0) && (aChar <= KEY_9)) )
@@ -2602,13 +2593,15 @@ void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
{
switch( aChar )
{
case KEY_POINT:
break;
case KEY_ESCAPE: // hide, do nothing
HideAndRestoreFocus();
break;
case KEY_RIGHT:
{
TextSelection aTextSelection( GetParentEditView()->GetSelection() );
if( aTextSelection.GetEnd().GetPara() != pCodeCompleteWindow->GetTextSelection().GetEnd().GetPara()-1 )
if( aTextSelection.GetEnd().GetPara() != GetTextSelection().GetEnd().GetPara()-1 )
{
HideAndRestoreFocus();
}
@@ -2617,7 +2610,7 @@ void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
case KEY_LEFT:
{
TextSelection aTextSelection( GetParentEditView()->GetSelection() );
if( aTextSelection.GetStart().GetIndex()-1 < pCodeCompleteWindow->GetTextSelection().GetStart().GetIndex() )
if( aTextSelection.GetStart().GetIndex()-1 < GetTextSelection().GetStart().GetIndex() )
{//leave the cursor where it is
HideAndRestoreFocus();
}
@@ -2625,23 +2618,23 @@ void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
}
case KEY_TAB:
{
TextSelection aTextSelection = pCodeCompleteWindow->pParent->GetLastHighlightPortionTextSelection();
OUString sTypedText = pCodeCompleteWindow->pParent->GetEditEngine()->GetText(aTextSelection);
TextSelection aTextSelection = pParent->GetLastHighlightPortionTextSelection();
OUString sTypedText = pParent->GetEditEngine()->GetText(aTextSelection);
if( !aFuncBuffer.isEmpty() )
{
sal_Int32 nInd = GetSelectedEntryPos();
if( nInd != LISTBOX_ENTRY_NOTFOUND )
{//if there is something selected
sal_Int32 nInd = m_xListBox->get_selected_index();
if (nInd != -1)
{
int nEntryCount = m_xListBox->n_children();
//if there is something selected
bool bFound = false;
if( nInd == GetEntryCount() )
nInd = 0;
for( sal_Int32 i = nInd; i != GetEntryCount(); ++i )
for (sal_Int32 i = nInd; i != nEntryCount; ++i)
{
OUString sEntry = GetEntry(i);
OUString sEntry = m_xListBox->get_text(i);
if( sEntry.startsWithIgnoreAsciiCase( aFuncBuffer.toString() )
&& (aFuncBuffer.toString() != sTypedText) && (i != nInd) )
{
SelectEntry( sEntry );
m_xListBox->select(i);
bFound = true;
break;
}
@@ -2651,7 +2644,7 @@ void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
GetParentEditView()->SetSelection( aTextSelection );
GetParentEditView()->DeleteSelected();
GetParentEditView()->InsertText( GetSelectedEntry() );
GetParentEditView()->InsertText(m_xListBox->get_selected_text());
}
}
break;
@@ -2664,8 +2657,8 @@ void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
{
//if there was something inserted by tab: add it to aFuncBuffer
TextSelection aSel( GetParentEditView()->GetSelection() );
TextPaM aEnd( GetParentEditView()->CursorEndOfLine(pCodeCompleteWindow->GetTextSelection().GetEnd()) );
GetParentEditView()->SetSelection(TextSelection(pCodeCompleteWindow->GetTextSelection().GetStart(), aEnd ) );
TextPaM aEnd( GetParentEditView()->CursorEndOfLine(GetTextSelection().GetEnd()) );
GetParentEditView()->SetSelection(TextSelection(GetTextSelection().GetStart(), aEnd ) );
OUString aTabInsertedStr( GetParentEditView()->GetSelected() );
GetParentEditView()->SetSelection( aSel );
@@ -2677,33 +2670,55 @@ void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
SetMatchingEntries();
}
else
pCodeCompleteWindow->ClearAndHide();
{
ClearAndHide();
bHandled = false;
}
break;
case KEY_RETURN:
InsertSelectedEntry();
break;
case KEY_UP: case KEY_DOWN:
NotifyEvent nEvt( MouseNotifyEvent::KEYINPUT, nullptr, &rKeyEvt );
PreNotify(nEvt);
case KEY_UP:
{
int nInd = m_xListBox->get_selected_index();
if (nInd)
m_xListBox->select(nInd - 1);
break;
}
case KEY_DOWN:
{
int nInd = m_xListBox->get_selected_index();
if (nInd + 1 < m_xListBox->n_children())
m_xListBox->select(nInd + 1);
break;
}
default:
bHandled = false;
break;
}
}
ListBox::KeyInput(rKeyEvt);
return bHandled;
}
void CodeCompleteListBox::HideAndRestoreFocus()
void CodeCompleteWindow::HideAndRestoreFocus()
{
pCodeCompleteWindow->Hide();
pCodeCompleteWindow->pParent->GrabFocus();
Hide();
pParent->GrabFocus();
}
CodeCompleteWindow::CodeCompleteWindow( EditorWindow* pPar )
: Window( pPar ),
pParent( pPar ),
pListBox( VclPtr<CodeCompleteListBox>::Create(this) )
CodeCompleteWindow::CodeCompleteWindow(EditorWindow* pPar)
: InterimItemWindow(pPar, "modules/BasicIDE/ui/codecomplete.ui", "CodeComplete")
, pParent(pPar)
, m_xListBox(m_xBuilder->weld_tree_view("treeview"))
{
SetSizePixel( Size(151,151) ); //default, later it changes
InitListBox();
m_xListBox->connect_row_activated(LINK(this, CodeCompleteWindow, ImplDoubleClickHdl));
m_xListBox->connect_changed(LINK(this, CodeCompleteWindow, ImplSelectHdl));
m_xListBox->connect_key_press(LINK(this, CodeCompleteWindow, KeyInputHdl));
m_xListBox->make_sorted();
m_xListBox->set_size_request(150, 150); // default, this will adopt the line length
SetSizePixel(m_xContainer->get_preferred_size());
}
CodeCompleteWindow::~CodeCompleteWindow()
@@ -2713,62 +2728,46 @@ CodeCompleteWindow::~CodeCompleteWindow()
void CodeCompleteWindow::dispose()
{
pListBox.disposeAndClear();
m_xListBox.reset();
pParent.clear();
vcl::Window::dispose();
}
void CodeCompleteWindow::InitListBox()
{
pListBox->SetSizePixel( Size(150,150) ); //default, this will adopt the line length
pListBox->Show();
pListBox->EnableQuickSelection( false );
InterimItemWindow::dispose();
}
void CodeCompleteWindow::InsertEntry( const OUString& aStr )
{
pListBox->InsertEntry( aStr );
m_xListBox->append_text(aStr);
}
void CodeCompleteWindow::ClearListBox()
{
pListBox->Clear();
pListBox->aFuncBuffer.setLength(0);
m_xListBox->clear();
aFuncBuffer.setLength(0);
}
void CodeCompleteWindow::SetTextSelection( const TextSelection& aSel )
{
aTextSelection = aSel;
m_aTextSelection = aSel;
}
void CodeCompleteWindow::ResizeAndPositionListBox()
{
if( pListBox->GetEntryCount() >= 1 )
{// if there is at least one element inside
if (m_xListBox->n_children() >= 1)
{
// if there is at least one element inside
// calculate basic position: under the current line
tools::Rectangle aRect = static_cast<TextEngine*>(pParent->GetEditEngine())->PaMtoEditCursor( pParent->GetEditView()->GetSelection().GetEnd() );
long nViewYOffset = pParent->GetEditView()->GetStartDocPos().Y();
Point aPos = aRect.BottomRight();// this variable will be used later (if needed)
aPos.setY( (aPos.Y() - nViewYOffset) + nBasePad );
OUString aLongestEntry = pListBox->GetEntry( 0 );// grab the longest one: max search
for( sal_Int32 i=1; i< pListBox->GetEntryCount(); ++i )
{
if( pListBox->GetEntry( i ).getLength() > aLongestEntry.getLength() )
aLongestEntry = pListBox->GetEntry( i );
}
// get column/line count
const sal_uInt16& nColumns = aLongestEntry.getLength();
const sal_uInt16 nLines = static_cast<sal_uInt16>( std::min( sal_Int32(6), pListBox->GetEntryCount() ));
// get line count
const sal_uInt16 nLines = static_cast<sal_uInt16>(std::min(6, m_xListBox->n_children()));
Size aSize = pListBox->CalcBlockSize( nColumns, nLines );
m_xListBox->set_size_request(-1, m_xListBox->get_height_rows(nLines));
Size aSize = m_xContainer->get_preferred_size();
//set the size
SetSizePixel( aSize );
//1 px smaller, to see the border
aSize.setWidth( aSize.getWidth() - 1 );
aSize.setHeight( aSize.getHeight() - 1 );
pListBox->SetSizePixel( aSize );
//calculate position
const tools::Rectangle aVisArea( pParent->GetEditView()->GetStartDocPos(), pParent->GetOutputSizePixel() ); //the visible area
@@ -2791,16 +2790,14 @@ void CodeCompleteWindow::ResizeAndPositionListBox()
void CodeCompleteWindow::SelectFirstEntry()
{
if( pListBox->GetEntryCount() > 0 )
{
pListBox->SelectEntryPos( 0 );
}
if (m_xListBox->n_children() > 0)
m_xListBox->select(0);
}
void CodeCompleteWindow::ClearAndHide()
{
ClearListBox();
pListBox->HideAndRestoreFocus();
HideAndRestoreFocus();
}
UnoTypeCodeCompletetor::UnoTypeCodeCompletetor( const std::vector< OUString >& aVect, const OUString& sVarType )
diff --git a/basctl/uiconfig/basicide/ui/codecomplete.ui b/basctl/uiconfig/basicide/ui/codecomplete.ui
new file mode 100644
index 0000000..6ef6fb4
--- /dev/null
+++ b/basctl/uiconfig/basicide/ui/codecomplete.ui
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface domain="basctl">
<requires lib="gtk+" version="3.18"/>
<object class="GtkTreeStore" id="liststore1">
<columns>
<!-- column-name text -->
<column type="gchararray"/>
<!-- column-name id -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkBox" id="CodeComplete">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="model">liststore1</property>
<property name="headers_visible">False</property>
<property name="headers_clickable">False</property>
<property name="enable_search">False</property>
<property name="search_column">1</property>
<property name="show_expanders">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</interface>