How can I simulate a Shift + Click on a Vaadin Button? - unit-testing

I created an application with Vaadin 23 containing buttons (com.vaadin.flow.component.button.Button) that reacts in differents ways when clicked with and without holding the shift key.
Button button = new Button("Click me", event -> {
if (event.isShiftKey()) {
System.out.println("Shift + click");
} else {
System.out.println("Click");
}
});
I am now trying to create unit tests for this but I don't know how to simulate the shift key. The Button class only offers a .click() method without any parameters.
button.click(); // The "else" part of the event is called
Is there a way (without creating a custom Button class) to simulate a shift + click in Vaadin ?

Button.click is implemented as:
public void click() {
fireEvent(new ClickEvent<>(this, false, 0, 0, 0, 0, 0, 0, false, false,
false, false));
}
Button.fireEvent is protected, but you can use ComponentUtil.fireEvent:
ComponentUtil.fireEvent(
this,
new ClickEvent<>(this, false, 0, 0, 0, 0, 0, 0, false, true, false, false));
// ^
// shiftKey

Related

how to set a value to list or text box using wxWidgets library

I've been struggling with converting the numbers on my buttons to the text box for my assignment. Basically what I'm trying to do is when a user presses for example when I click on 7 it should appear in the text box but currently in my Button Pressed method it only puts in a . instead of 7 and I'm not too familiar with the wxWidgets library classes. is there another command or method I can use?
wxBEGIN_EVENT_TABLE(calMain, wxFrame)
EVT_BUTTON(100, ButtonPressed)
wxEND_EVENT_TABLE()
calMain::calMain() : wxFrame(nullptr, wxID_ANY, "Calculator UI!", wxPoint(50, 50), wxSize(335, 545))
{
wxFont font(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false);
m_txt1 = new wxTextCtrl(this,wxID_ANY, " ",wxPoint(0, 21), wxSize(322, 50));
CalButton = new wxButton(this, 100, "7", wxPoint(30, 156), wxSize(50, 70));
CalButton->SetFont(font);
}
void calMain::ButtonPressed(wxCommandEvent& evt)
{
m_txt1->SetLabelText(CalButton->GetLabelText());
evt.Skip();
}
You need to use wxTextCtrl::SetValue() (or ChangeValue(), which is very similar, but doesn't generate any events about the change in the text control) to change the value (not the label) of wxTextCtrl.

Why is my combobox overwriting my label in my grid layout in QT 5.15?

I have a form that was giving me a SegFault Exception so I broke it down and commented out everything but the mainwindow itself. Then I uncommented out the first 2 controls to display. I'm using a qgridlayout but it's not showing things correctly. When I show just the first item, it shows the label with the & instead of an underline - which makes sense since I don't show the "buddy". If I show both though or if I add the 'setBuddy' in then the buddy overwrites the label in the grid at 0,0. The label is supposed to be at 0,0 and the buddy/combo box is at 0, 1. I need to keep adding things in and my alternative is to use QHBoxLayouts repeatedly and I'm not nuts about that at all as things won't be aligned. Here's just the CPP code for the MainWindow to see:
QComboBox *MainWindow::getSourceComboBox()
{
if(mCboSource == nullptr)
{
mCboSource = new QComboBox(this);
mCboSource->addItems({{"URL", "Text", "Database"}});
mCboSource->setCurrentIndex(0);
mCboSource->setEditable(false);
//connect(mCboSource, SIGNAL(QComboBox::currentTextChanged(QString &)), this, SLOT(MainWindow::sourceChanged(QString &)));
}
return(mCboSource);
}
QLabel *MainWindow::getSourceLabel()
{
if(mLblSource == nullptr)
{
mLblSource = new QLabel("&Source:", this);
mLblSource->setBuddy(getSourceComboBox());
mLblSource->setAutoFillBackground(false);
}
return(mLblSource);
}
void MainWindow::initControls()
{
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(this->getSourceLabel(), 0, 0, 1, 1);
layout->addWidget(this->getSourceComboBox(), 0, 1, 1, 1);
/*layout->addWidget(this->getConfigButton(), 0, 2);
layout->addWidget(this->getDBPathLabel(), 1, 0);
layout->addWidget(this->getDBPathText(), 1, 1);
layout->addWidget(this->getBrowseButton(), 1, 2);
layout->addWidget(this->getDataTable(), 2, 0, 1, 3);
layout->addWidget(this->getButtonPanel(), 3, 0, 1, 3);*/
setLayout(layout);
}
void MainWindow::initWindow()
{
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
initControls();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, mCboSource(nullptr)
//, mLblDBPath(nullptr)
, mLblSource(nullptr)
/*, mTxtDBPath(nullptr)
, mBtnBrowse(nullptr)
, mBtnConfig(nullptr)
, mTblData(nullptr)*/
{
initWindow();
}
MainWindow::~MainWindow()
{ }
But what could be wrong w/ the QT code???
You are adding items almost as a central widget so you need to create a central widget and add the items and layout to that then add that central widget to the main window. That should solve the problem!

Customising a dynamic layout at runtime based on control visibility

I have a multi-purpose CDialog that supports resizing. It can display content in 3 variations.
Variation 1:
Variation 2:
Variation 3:
The dialogue controls are using the dynamic layout settings from the resource editor.
Variation 1 is fine and need no changes.
Variation 2 does not display the combo and date button. As a result I would like the "Text will ..." label to be down at the bottom and the "edit" box to be taller.
Variation 3 has a similar issue where the date button should move to the bottom and the edit box be taller.
Can this be achieved by changing the dynamic layout in code?
Update
I tried this in OnInitDialog:
if (!m_bShowWeekCombo)
{
CRect rctCombo;
m_cbWeek.GetWindowRect(rctCombo);
ScreenToClient(rctCombo);
CRect rctNote;
m_staticInfo.GetWindowRect(rctNote);
ScreenToClient(rctNote);
m_staticInfo.MoveWindow(rctCombo.left, rctCombo.top, rctNote.Width(), rctNote.Height());
}
At first I thought it was working:
The note is now at the bottom. But as soon as I resize the window:
The note has reverted to the original position.
I know I have this answer to a similar issue but do I really have to re-build the whole layout?
Update 2
if (!m_bShowWeekCombo)
{
CRect rctEdit;
m_editText.GetWindowRect(rctEdit);
ScreenToClient(rctEdit);
CRect rctCombo;
m_cbWeek.GetWindowRect(rctCombo);
ScreenToClient(rctCombo);
CRect rctNote;
m_staticInfo.GetWindowRect(rctNote);
ScreenToClient(rctNote);
//m_staticInfo.MoveWindow(rctCombo.left, rctCombo.top, rctNote.Width(), rctNote.Height());
m_staticInfo.SetWindowPos(NULL, rctCombo.left, rctCombo.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
m_editText.SetWindowPos(NULL, 0, 0, rctEdit.Width(), rctEdit.Height() + (rctCombo.top - rctNote.top),
SWP_NOMOVE | SWP_NOZORDER);
if (m_pDynamicLayout)
{
if (!m_pDynamicLayout->HasItem(m_staticInfo.m_hWnd))
{
m_pDynamicLayout->AddItem(m_staticInfo.m_hWnd,
CMFCDynamicLayout::MoveVertical(100), CMFCDynamicLayout::SizeHorizontal(100));
}
else
{
TRACE(L"item already has dynamic move/size\n");
}
if (!m_pDynamicLayout->HasItem(m_editText.m_hWnd))
{
m_pDynamicLayout->AddItem(m_editText.m_hWnd,
CMFCDynamicLayout::MoveNone(), CMFCDynamicLayout::SizeHorizontalAndVertical(100, 100));
}
else
{
TRACE(L"item already has dynamic move/size\n");
}
}
}
When I try the above the control width is the original width, even though the dialog had restored to wider dialog width.
CMFCDynamicLayout reads the dialog resource, it stores the coordinates for the child controls as well as their dynamic resize/move properties.
This is all done in CDialog::OnInitDialog. If you move the child control, example, m_staticInfo then CMFCDynamicLayout doesn't know you moved/resized the control. So upon the next dialog resize request, CMFCDynamicLayout uses the old values.
You can add dynamic resize/move for all controls expcept m_staticInfo and other controls which you intend to move manually. Then add m_staticInfo separately:
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
CRect rctCombo;
m_cbWeek.GetWindowRect(rctCombo);
ScreenToClient(rctCombo);
m_staticInfo.SetWindowPos(NULL, rctCombo.left, rctCombo.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);
if(m_pDynamicLayout)
{
if(!m_pDynamicLayout->HasItem(m_staticInfo.m_hWnd))
{
m_pDynamicLayout->AddItem(m_staticInfo.m_hWnd,
CMFCDynamicLayout::MoveVertical(100), CMFCDynamicLayout::SizeNone());
}
else
{
TRACE(L"item already has dynamic move/size\n");
AfxDebugBreak(0);
}
}
return 1;
}
Internally, MFC calls LoadDynamicLayoutResource(m_lpszTemplateName) to initialize dynamic size/move. But documentation says not to use this method directly.
Clarification
If you are using a dialog that supports resizing then you must remember to calculate the new width and height when you move the control to the new position. You would then use one of the appropriate Size calls. For example:
// The EDIT control height now needs increasing
iNewEditHeight = rctButton.top - iTextMarginY - rctEdit.top;
m_editText.SetWindowPos(nullptr, 0, 0, iNewWidth, iNewEditHeight, SWP_NOMOVE | SWP_NOZORDER);
It is up to you to workout how you want your control initially re-sized.
Then, in OnInitDialog I called a new method:
void CEditTextDlg::SetupDynamicLayout()
{
if (m_pDynamicLayout != nullptr)
{
m_pDynamicLayout->AddItem(IDC_BUTTON_INSERT_DATE,
CMFCDynamicLayout::MoveHorizontalAndVertical(100, 100), CMFCDynamicLayout::SizeNone());
m_pDynamicLayout->AddItem(IDC_STATIC_INFO,
CMFCDynamicLayout::MoveVertical(100), CMFCDynamicLayout::SizeHorizontal(100));
m_pDynamicLayout->AddItem(IDC_EDIT_TEXT,
CMFCDynamicLayout::MoveNone(), CMFCDynamicLayout::SizeHorizontalAndVertical(100, 100));
}
}
If you don't set the width correctly when using SetWindowPos and only use SizeNone() it will not resize correctly.

2 CMFCTabControls on different position, but tabs stay on the same place

I've would like to have 2 sets of tabs on my CScrollView -derived class, so I put 2 CMFCTabCtrs side by side. The tab controls are filled with dialogs (currently same class, but different objects for test purpose, later different dialogs for each tab control).
The problem is while the controls themselves are placed besides each other as desired. the tabs or dialogs from the second tab control appear in area of the first tab controls, thus overlapping with it.
on the picture above the dialog on the left (currently minimalistic for testing) actually belongs to the control on the right. the dialogs inside of tab are childs of the view.
Resource of the dialog:
IDD_COMBATANTDLG DIALOGEX 0, 0, 320, 331
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
GROUPBOX "Flotte",IDC_STATIC,19,18,192,175,BS_FLAT
LTEXT "Static",IDC_STATIC,91,94,19,8
EDITTEXT IDC_EDIT1,136,118,40,14,ES_AUTOHSCROLL
END
declarations:
class SimDataInput : public CScrollView
{
protected: // create from serialization only
SimDataInput();
DECLARE_DYNCREATE(SimDataInput)
// Attributes
private:
CMFCTabCtrl combatant_tabs[2];//tabs
std::vector<CombatantDlg*> p2combatdlg[2];//stores pointers to dialog
const CStringW attdef[2] = { L"Angreifer ", L"Verteidiger " };//standard labels for respective tab controls
............
from OnInitialUpdate():
void SimDataInput::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
for (auto i = 0; i < 2;i++)
{
CStringW label ( attdef[i]);
RECT pos = RECT{ i * 400, 0, 400 + i * 400, 500 };
combatant_tabs[i].Create(CMFCTabCtrl::STYLE_3D, pos, this,10000+i, CMFCTabCtrl::LOCATION_TOP,TRUE);//create tab
combatant_tabs[i].EnableTabSwap(FALSE);
combatant_tabs[i].EnableActiveTabCloseButton();
//combatant_tabs[sim::ATT].EnableTabDocumentsMenu(TRUE);
p2combatdlg[i].reserve(16);
p2combatdlg[i].emplace_back();//create pointer
p2combatdlg[i].back() = new CombatantDlg(this);//initialize pointer to the new dialog
p2combatdlg[i].back()->Create(IDD_COMBATANTDLG, this);//create dialog
//p2combatdlg[i].back()->SetWindowPos(&combatant_tabs[i], 400, 0, 0, 0, SWP_NOZORDER | SWP_SHOWWINDOW);//tried this -doesn't help
label.AppendFormat(L"%d",1);
combatant_tabs[i].InsertTab(p2combatdlg[i].back(),label , 0, -1, FALSE);//insert the first tab
}
.......
next function inserts new tabs after pushing respective button
void SimDataInput::OnCombatant(UINT nID)//used by ON_COMMAND_RANGE for both tab controls
{
nID -= ID_ATTACKER;
if (combatant_tabs[nID].GetTabsNum() == 16)
return;
CStringW label ( attdef[nID]);
p2combatdlg[nID].emplace_back();
label.AppendFormat(L"%d", p2combatdlg[nID].size());
p2combatdlg[nID].back() = new CombatantDlg(this);
p2combatdlg[nID].back()->Create(IDD_COMBATANTDLG, this);
combatant_tabs[nID].InsertTab(p2combatdlg[nID].back(), label , combatant_tabs[nID].GetTabsNum(), -1, FALSE);
combatant_tabs[nID].SetActiveTab(combatant_tabs[nID].GetTabsNum() - 1);
// TODO: Add your command handler code here
}
After all, making the CMFCTabCtrls parents to the contained dialog corrected the behaviour. I had to store the pointer to the former parentsd insidethe dialogs to make the access easier

Auto Hiding CDockablePane on creation

I have 3 dockable panes, each containing 1 image. One is on the left, one on the right and one not visible. The problem is, I would like to have the one on the right hidden by default to let the one on the left take the entire space. I have searched through the doc to find I should call the following on my pane, but nothing happens.
ToggleAutoHide();
I don't know what I am missing... here is my creation code in case it helps:
// image docking panel creation
if (!m_wndRawImage.Create(_T("Raw Image"), this, imgRect, TRUE, ID_VIEW_RAWIMGWND, dwPaneStyle| CBRS_RIGHT, AFX_CBRS_REGULAR_TABS, AFX_CBRS_RESIZE))
{
TRACE0("Failed to create image tab window\n");
return -1;
}
if (!m_wndRefImage.Create(_T("Reference Image"), this, imgRect, TRUE, ID_VIEW_REFIMGWND, dwPaneStyle| CBRS_RIGHT))
{
TRACE0("Failed to create image tab window\n");
return -1;
}
if (!m_wndCalibImage.Create(_T("Calibrated Image"), this, imgRect, TRUE, ID_VIEW_CALIBIMGWND, dwPaneStyle| CBRS_RIGHT))
{
TRACE0("Failed to create image tab window\n");
return -1;
}
m_wndImagePane1.EnableDocking(CBRS_ALIGN_RIGHT | CBRS_ALIGN_LEFT);
m_wndImagePane2.EnableDocking(CBRS_ALIGN_RIGHT | CBRS_ALIGN_LEFT);
m_wndImagePane3.EnableDocking(CBRS_ALIGN_RIGHT | CBRS_ALIGN_LEFT);
CDockingManager::SetDockingMode(DT_SMART);
EnableDocking(CBRS_ALIGN_ANY);
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// image panes
DockPane(&m_wndImagePane3);
CDockablePane* pTabbedBar2 = NULL;
m_wndImagePane2.AttachToTabWnd(&m_wndImagePane3, DM_SHOW, FALSE, &pTabbedBar2);
m_wndImagePane2.ShowPane(FALSE, FALSE, FALSE);
m_wndImagePane3.ShowPane(TRUE, FALSE, TRUE);
m_wndImagePane3.ToggleAutoHide(); //<---- Problem is here
DockPane(&m_wndImagePane1);
m_wndImagePane1.ShowPane(TRUE, FALSE, TRUE);
Thanks!
if I was understand your problem correctly, you want to hide a pane in app startup.
I use ON_WM_SHOWWINDOW() Message to hide pane. like this:
Add this to CMainFrame Class declaration:
afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
And add this to Message map:
ON_WM_SHOWWINDOW()
And add this to your main code:
void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
CFrameWndEx::OnShowWindow(bShow, nStatus);
// Hide Properties pane in startup
m_wndProperties.SetAutoHideMode(FALSE, CBRS_ALIGN_ANY);
m_wndProperties.ShowPane(FALSE, FALSE, FALSE);
}
Hope it can help!