1847 lines
69 KiB
C++
1847 lines
69 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: tests/controls/propgrid.cpp
|
|
// Purpose: wxPropertyGrid unit tests
|
|
// Author: Artur Wieczorek, Jaakko Salli
|
|
// Created: 2023-01-12
|
|
// Copyright: (c) 2023 wxWidgets development team
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "testprec.h"
|
|
|
|
#if wxUSE_PROPGRID
|
|
|
|
#include "wx/app.h"
|
|
#include "wx/artprov.h"
|
|
#include "wx/dcmemory.h"
|
|
#if wxUSE_DATEPICKCTRL
|
|
#include "wx/datectrl.h"
|
|
#endif
|
|
|
|
#include "wx/propgrid/propgrid.h"
|
|
#include "wx/propgrid/manager.h"
|
|
#include "wx/propgrid/advprops.h"
|
|
|
|
#include "waitfor.h"
|
|
|
|
#include <random>
|
|
#include <vector>
|
|
|
|
// Prepare RNG
|
|
static std::random_device s_rd;
|
|
static std::default_random_engine s_rng(s_rd());
|
|
|
|
static void PopulateWithStandardItems(wxPropertyGridManager* pgManager)
|
|
{
|
|
wxPropertyGridPage* pg = pgManager->GetPage("Standard Items");
|
|
|
|
pg->Append(new wxPropertyCategory("Appearance", wxPG_LABEL));
|
|
|
|
pg->Append(new wxStringProperty("Label", wxPG_LABEL, "PropertyGridTest"));
|
|
pg->Append(new wxFontProperty("Font", wxPG_LABEL));
|
|
pg->SetPropertyHelpString("Font", "Editing this will change font used in the property grid.");
|
|
|
|
pg->Append(new wxSystemColourProperty("Margin Colour", wxPG_LABEL, pg->GetGrid()->GetMarginColour()));
|
|
|
|
pg->Append(new wxSystemColourProperty("Cell Colour", wxPG_LABEL, pg->GetGrid()->GetCellBackgroundColour()));
|
|
pg->Append(new wxSystemColourProperty("Cell Text Colour", wxPG_LABEL, pg->GetGrid()->GetCellTextColour()));
|
|
pg->Append(new wxSystemColourProperty("Line Colour", wxPG_LABEL, pg->GetGrid()->GetLineColour()));
|
|
static const wxString flags_prop_labels[] = {
|
|
"wxICONIZE", "wxCAPTION", "wxMINIMIZE_BOX", "wxMAXIMIZE_BOX"
|
|
};
|
|
long flags_prop_values[] = { wxICONIZE, wxCAPTION, wxMINIMIZE_BOX, wxMAXIMIZE_BOX };
|
|
wxPGChoices combinedFlags;
|
|
combinedFlags.Add(WXSIZEOF(flags_prop_labels), flags_prop_labels, flags_prop_values);
|
|
pg->Append(new wxFlagsProperty("Window Styles", wxPG_LABEL,
|
|
combinedFlags, wxTheApp->GetTopWindow()->GetWindowStyle()));
|
|
|
|
pg->Append(new wxCursorProperty("Cursor", wxPG_LABEL));
|
|
|
|
pg->Append(new wxPropertyCategory("Position", "PositionCategory"));
|
|
pg->SetPropertyHelpString("PositionCategory", "Change in items in this category will cause respective changes in frame.");
|
|
|
|
pg->Append(new wxIntProperty("Height", wxPG_LABEL, 480L));
|
|
pg->SetPropertyAttribute("Height", wxPG_ATTR_MIN, 10L);
|
|
pg->SetPropertyAttribute("Height", wxPG_ATTR_MAX, 2048L);
|
|
pg->SetPropertyAttribute("Height", wxPG_ATTR_UNITS, "Pixels");
|
|
|
|
pg->SetPropertyValueUnspecified("Height");
|
|
pg->SetPropertyAttribute("Height", wxPG_ATTR_HINT, "Enter new height for window");
|
|
|
|
pg->SetPropertyHelpString("Height", "This property uses attributes \"Units\" and \"Hint\".");
|
|
|
|
pg->Append(new wxIntProperty("Width", wxPG_LABEL, 640L));
|
|
pg->SetPropertyAttribute("Width", wxPG_ATTR_MIN, 10L);
|
|
pg->SetPropertyAttribute("Width", wxPG_ATTR_MAX, 2048L);
|
|
pg->SetPropertyAttribute("Width", wxPG_ATTR_UNITS, "Pixels");
|
|
|
|
pg->SetPropertyValueUnspecified("Width");
|
|
pg->SetPropertyAttribute("Width", wxPG_ATTR_HINT, "Enter new width for window");
|
|
pg->SetPropertyHelpString("Width", "This property uses attributes \"Units\" and \"Hint\".");
|
|
|
|
pg->Append(new wxIntProperty("X", wxPG_LABEL, 10L));
|
|
pg->SetPropertyAttribute("X", wxPG_ATTR_UNITS, "Pixels");
|
|
pg->SetPropertyHelpString("X", "This property uses \"Units\" attribute.");
|
|
|
|
pg->Append(new wxIntProperty("Y", wxPG_LABEL, 10L));
|
|
pg->SetPropertyAttribute("Y", wxPG_ATTR_UNITS, "Pixels");
|
|
pg->SetPropertyHelpString("Y", "This property uses \"Units\" attribute.");
|
|
|
|
const wxString disabledHelpString = "This property is simply disabled.";
|
|
|
|
pg->Append(new wxPropertyCategory("Environment", wxPG_LABEL));
|
|
pg->Append(new wxStringProperty("Operating System", wxPG_LABEL, ::wxGetOsDescription()));
|
|
|
|
pg->Append(new wxStringProperty("User Id", wxPG_LABEL, ::wxGetUserId()));
|
|
pg->Append(new wxDirProperty("User Home", wxPG_LABEL, ::wxGetUserHome()));
|
|
pg->Append(new wxStringProperty("User Name", wxPG_LABEL, ::wxGetUserName()));
|
|
|
|
// Disable some of them
|
|
pg->DisableProperty("Operating System");
|
|
pg->DisableProperty("User Id");
|
|
pg->DisableProperty("User Name");
|
|
|
|
pg->SetPropertyHelpString("Operating System", disabledHelpString);
|
|
pg->SetPropertyHelpString("User Id", disabledHelpString);
|
|
pg->SetPropertyHelpString("User Name", disabledHelpString);
|
|
|
|
pg->Append(new wxPropertyCategory("More Examples", wxPG_LABEL));
|
|
|
|
pg->Append(new wxLongStringProperty("Information", wxPG_LABEL,
|
|
"Editing properties will have immediate effect on this window, "
|
|
"and vice versa (at least in most cases, that is)."
|
|
));
|
|
pg->SetPropertyHelpString("Information", "This property is read-only.");
|
|
|
|
pg->SetPropertyReadOnly("Information", true);
|
|
|
|
// Set test information for cells in columns 3 and 4
|
|
// (reserve column 2 for displaying units)
|
|
wxBitmap bmp = wxArtProvider::GetBitmap(wxART_FOLDER);
|
|
|
|
for ( auto it = pg->GetGrid()->GetIterator(); !it.AtEnd(); ++it )
|
|
{
|
|
wxPGProperty* p = *it;
|
|
if ( p->IsCategory() )
|
|
continue;
|
|
|
|
pg->SetPropertyCell(p, 3, "Cell 3", bmp);
|
|
pg->SetPropertyCell(p, 4, "Cell 4", wxBitmapBundle(), *wxWHITE, *wxBLACK);
|
|
}
|
|
}
|
|
|
|
static void PopulateWithExamples(wxPropertyGridManager* pgManager)
|
|
{
|
|
wxPropertyGridPage* pg = pgManager->GetPage("Examples");
|
|
wxPGProperty* pid;
|
|
wxPGProperty* prop;
|
|
|
|
pg->Append(new wxIntProperty("IntProperty", wxPG_LABEL, 12345678L));
|
|
|
|
#if wxUSE_SPINBTN
|
|
pg->Append(new wxIntProperty("SpinCtrl", wxPG_LABEL, 0L));
|
|
|
|
pg->SetPropertyEditor("SpinCtrl", wxPGEditor_SpinCtrl);
|
|
pg->SetPropertyAttribute("SpinCtrl", wxPG_ATTR_MIN, -2L);
|
|
pg->SetPropertyAttribute("SpinCtrl", wxPG_ATTR_MAX, 16384L);
|
|
pg->SetPropertyAttribute("SpinCtrl", wxPG_ATTR_SPINCTRL_STEP, 2L);
|
|
pg->SetPropertyAttribute("SpinCtrl", wxPG_ATTR_SPINCTRL_MOTION, true);
|
|
|
|
pg->SetPropertyHelpString("SpinCtrl",
|
|
"This is regular wxIntProperty, which editor has been "
|
|
"changed to wxPGEditor_SpinCtrl.");
|
|
|
|
#endif
|
|
|
|
// Add bool property
|
|
pg->Append(new wxBoolProperty("BoolProperty", wxPG_LABEL, false));
|
|
|
|
// Add bool property with check box
|
|
pg->Append(new wxBoolProperty("BoolProperty with CheckBox", wxPG_LABEL, false));
|
|
pg->SetPropertyAttribute("BoolProperty with CheckBox", wxPG_BOOL_USE_CHECKBOX, true);
|
|
|
|
pg->SetPropertyHelpString("BoolProperty with CheckBox",
|
|
"Property attribute wxPG_BOOL_USE_CHECKBOX has been set to true.");
|
|
|
|
prop = pg->Append(new wxFloatProperty("FloatProperty", wxPG_LABEL, 1234500.23));
|
|
prop->SetAttribute(wxPG_ATTR_MIN, -100.12);
|
|
|
|
pg->Append(new wxLongStringProperty("LongStringProperty", "LongStringProp",
|
|
"This is much longer string than the first one. Edit it by clicking the button."));
|
|
|
|
wxArrayString example_array;
|
|
example_array.Add("String 1");
|
|
example_array.Add("String 2");
|
|
example_array.Add("String 3");
|
|
pg->Append(new wxArrayStringProperty("ArrayStringProperty", wxPG_LABEL, example_array));
|
|
|
|
prop = new wxFileProperty("FileProperty", "TextFile");
|
|
pg->Append(prop);
|
|
|
|
prop->SetAttribute(wxPG_FILE_WILDCARD, "Text Files (*.txt)|*.txt");
|
|
prop->SetAttribute(wxPG_DIALOG_TITLE, "Custom File Dialog Title");
|
|
prop->SetAttribute(wxPG_FILE_SHOW_FULL_PATH, false);
|
|
|
|
#ifdef __WXMSW__
|
|
prop->SetAttribute(wxPG_FILE_SHOW_RELATIVE_PATH, "C:\\Windows");
|
|
pg->SetPropertyValue(prop, "C:\\Windows\\System32\\msvcrt71.dll");
|
|
#endif
|
|
|
|
#if wxUSE_IMAGE
|
|
pg->Append(new wxImageFileProperty("ImageFile", wxPG_LABEL));
|
|
#endif
|
|
|
|
pid = pg->Append(new wxColourProperty("ColourProperty", wxPG_LABEL, *wxRED));
|
|
pg->SetPropertyEditor("ColourProperty", wxPGEditor_ComboBox);
|
|
pg->GetProperty("ColourProperty")->SetAutoUnspecified(true);
|
|
pg->SetPropertyHelpString("ColourProperty",
|
|
"wxPropertyGrid::SetPropertyEditor method has been used to change "
|
|
"editor of this property to wxPGEditor_ComboBox)");
|
|
|
|
pid = pg->Append(new wxColourProperty("ColourPropertyWithAlpha",
|
|
wxPG_LABEL, wxColour(15, 200, 95, 128)));
|
|
pg->SetPropertyAttribute("ColourPropertyWithAlpha", wxPG_COLOUR_HAS_ALPHA, true);
|
|
pg->SetPropertyHelpString("ColourPropertyWithAlpha",
|
|
"Attribute \"HasAlpha\" is set to true for this property.");
|
|
|
|
pg->Append(new wxColourProperty("ColourProperty2", wxPG_LABEL, *wxGREEN));
|
|
|
|
static const wxString enum_prop_labels[] = { "One Item",
|
|
"Another Item", "One More", "This Is Last" };
|
|
|
|
static long enum_prop_values[] = { 40, 80, 120, 160 };
|
|
|
|
pg->Append(new wxEnumProperty("EnumProperty", wxPG_LABEL,
|
|
wxArrayString(WXSIZEOF(enum_prop_labels), enum_prop_labels),
|
|
wxArrayInt(enum_prop_values, enum_prop_values + WXSIZEOF(enum_prop_values)), 80));
|
|
|
|
wxPGChoices soc;
|
|
|
|
soc.Set(wxArrayString(WXSIZEOF(enum_prop_labels), enum_prop_labels),
|
|
wxArrayInt(enum_prop_values, enum_prop_values + WXSIZEOF(enum_prop_values)));
|
|
|
|
// add extra items
|
|
soc.Add("Look, it continues", 200);
|
|
soc.Add("Even More", 240);
|
|
soc.Add("And More", 280);
|
|
soc.Add(wxString(), 300);
|
|
soc.Add("True End of the List", 320);
|
|
|
|
soc[1].SetFgCol(*wxRED);
|
|
soc[1].SetBgCol(*wxLIGHT_GREY);
|
|
soc[2].SetFgCol(*wxGREEN);
|
|
soc[2].SetBgCol(*wxLIGHT_GREY);
|
|
soc[3].SetFgCol(*wxBLUE);
|
|
soc[3].SetBgCol(*wxLIGHT_GREY);
|
|
soc[4].SetBitmap(wxArtProvider::GetBitmap(wxART_FOLDER));
|
|
|
|
pg->Append(new wxEnumProperty("EnumProperty 2", wxPG_LABEL, soc, 240));
|
|
pg->GetProperty("EnumProperty 2")->AddChoice("Testing Extra", 360);
|
|
|
|
pg->Append(new wxEnumProperty("EnumProperty 3", wxPG_LABEL, soc, 240));
|
|
|
|
pg->GetProperty("EnumProperty 3")->SetAttribute(wxPG_ATTR_HINT, "Dummy Hint");
|
|
|
|
pg->SetPropertyHelpString("EnumProperty 3", "This property uses \"Hint\" attribute.");
|
|
|
|
pg->Append(new wxEnumProperty("EnumProperty 4", wxPG_LABEL, soc, 240));
|
|
pg->GetProperty("EnumProperty 4")->AddChoice("4th only", 360);
|
|
|
|
pg->SetPropertyHelpString("EnumProperty 4",
|
|
"Should have one extra item when compared to EnumProperty 3");
|
|
|
|
pg->Append(new wxEnumProperty("EnumProperty With Bitmap", "EnumProperty 5", soc, 280));
|
|
pg->SetPropertyHelpString("EnumProperty 5", "Should have bitmap in front of the displayed value");
|
|
wxBitmap bmpVal = wxArtProvider::GetBitmap(wxART_REMOVABLE);
|
|
pg->SetPropertyImage("EnumProperty 5", bmpVal);
|
|
|
|
pg->Append(new wxStringProperty("Password", wxPG_LABEL, "password"));
|
|
pg->SetPropertyAttribute("Password", wxPG_STRING_PASSWORD, true);
|
|
pg->SetPropertyHelpString("Password", "Has attribute wxPG_STRING_PASSWORD set to true");
|
|
|
|
pg->Append(new wxDirProperty("DirProperty", wxPG_LABEL, ::wxGetUserHome()));
|
|
pg->SetPropertyAttribute("DirProperty", wxPG_DIALOG_TITLE, "This is a custom dir dialog title");
|
|
|
|
pg->Append(new wxStringProperty("StringProperty", wxPG_LABEL));
|
|
pg->SetPropertyMaxLength("StringProperty", 6);
|
|
pg->SetPropertyHelpString("StringProperty","Max length of this text has been limited to 6.");
|
|
|
|
pg->SetPropertyValue("StringProperty", "some text");
|
|
|
|
pg->Append(new wxStringProperty("StringProperty AutoComplete", wxPG_LABEL));
|
|
|
|
wxArrayString autoCompleteStrings;
|
|
autoCompleteStrings.Add("One choice");
|
|
autoCompleteStrings.Add("Another choice");
|
|
autoCompleteStrings.Add("Another choice, yeah");
|
|
autoCompleteStrings.Add("Yet another choice");
|
|
autoCompleteStrings.Add("Yet another choice, bear with me");
|
|
pg->SetPropertyAttribute("StringProperty AutoComplete", wxPG_ATTR_AUTOCOMPLETE, autoCompleteStrings);
|
|
|
|
pg->SetPropertyHelpString("StringProperty AutoComplete",
|
|
"AutoComplete attribute has been set for this property.");
|
|
|
|
pg->Append(new wxStringProperty("StringPropertyWithBitmap", wxPG_LABEL, "Test Text"));
|
|
wxBitmap myTestBitmap1x(60, 15, 32);
|
|
{
|
|
wxMemoryDC mdc(myTestBitmap1x);
|
|
mdc.SetBackground(*wxWHITE_BRUSH);
|
|
mdc.Clear();
|
|
mdc.SetPen(*wxBLACK_PEN);
|
|
mdc.SetBrush(*wxWHITE_BRUSH);
|
|
mdc.DrawRectangle(0, 0, 60, 15);
|
|
mdc.DrawLine(0, 0, 59, 14);
|
|
mdc.SetTextForeground(*wxBLACK);
|
|
mdc.DrawText("x1", 0, 0);
|
|
}
|
|
wxBitmap myTestBitmap2x(120, 30, 32);
|
|
{
|
|
wxMemoryDC mdc(myTestBitmap2x);
|
|
mdc.SetBackground(*wxWHITE_BRUSH);
|
|
mdc.Clear();
|
|
mdc.SetPen(wxPen(*wxBLUE, 2));
|
|
mdc.SetBrush(*wxWHITE_BRUSH);
|
|
mdc.DrawRectangle(0, 0, 120, 30);
|
|
mdc.DrawLine(0, 0, 119, 31);
|
|
mdc.SetTextForeground(*wxBLUE);
|
|
wxFont f = mdc.GetFont();
|
|
f.SetPixelSize(2 * f.GetPixelSize());
|
|
mdc.SetFont(f);
|
|
mdc.DrawText("x2", 0, 0);
|
|
}
|
|
myTestBitmap2x.SetScaleFactor(2);
|
|
pg->SetPropertyImage("StringPropertyWithBitmap", wxBitmapBundle::FromBitmaps(myTestBitmap1x, myTestBitmap2x));
|
|
|
|
// this value array would be optional if values matched string indexes
|
|
static const wxString flags_prop_labels[] = {
|
|
"wxICONIZE", "wxCAPTION", "wxMINIMIZE_BOX", "wxMAXIMIZE_BOX"
|
|
};
|
|
long flags_prop_values[] = { wxICONIZE, wxCAPTION, wxMINIMIZE_BOX, wxMAXIMIZE_BOX };
|
|
wxPGChoices combinedFlags;
|
|
combinedFlags.Add(WXSIZEOF(flags_prop_labels), flags_prop_labels, flags_prop_values);
|
|
pg->Append(new wxFlagsProperty("FlagsProperty", wxPG_LABEL,
|
|
combinedFlags, wxTheApp->GetTopWindow()->GetWindowStyle() ) );
|
|
pg->SetPropertyAttribute("FlagsProperty", wxPG_BOOL_USE_CHECKBOX, true, wxPGPropertyValuesFlags::Recurse);
|
|
|
|
wxArrayString tchoices;
|
|
tchoices.Add("Cabbage");
|
|
tchoices.Add("Carrot");
|
|
tchoices.Add("Onion");
|
|
tchoices.Add("Potato");
|
|
tchoices.Add("Strawberry");
|
|
|
|
wxArrayString tchoicesValues;
|
|
tchoicesValues.Add("Carrot");
|
|
tchoicesValues.Add("Potato");
|
|
|
|
pg->Append(new wxEnumProperty("EnumProperty X", wxPG_LABEL, tchoices));
|
|
|
|
pg->Append(new wxMultiChoiceProperty("MultiChoiceProperty", wxPG_LABEL, tchoices, tchoicesValues));
|
|
pg->SetPropertyAttribute("MultiChoiceProperty", wxPG_ATTR_MULTICHOICE_USERSTRINGMODE, 1);
|
|
|
|
pg->Append(new wxUIntProperty("UIntProperty", wxPG_LABEL, wxULongLong(wxULL(0xFEEEFEEEFEEE))));
|
|
pg->SetPropertyAttribute("UIntProperty", wxPG_UINT_PREFIX, wxPG_PREFIX_NONE);
|
|
pg->SetPropertyAttribute("UIntProperty", wxPG_UINT_BASE, wxPG_BASE_HEX);
|
|
|
|
wxPGChoices eech;
|
|
eech.Add("Choice 1");
|
|
eech.Add("Choice 2");
|
|
eech.Add("Choice 3");
|
|
pg->Append(new wxEditEnumProperty("EditEnumProperty", wxPG_LABEL, eech, "Choice not in the list"));
|
|
|
|
pg->GetProperty("EditEnumProperty")->SetAttribute(wxPG_ATTR_HINT, "Dummy Hint");
|
|
|
|
#if wxUSE_DATETIME
|
|
//
|
|
// wxDateTimeProperty
|
|
pg->Append(new wxDateProperty("DateProperty", wxPG_LABEL, wxDateTime::Now()));
|
|
|
|
#if wxUSE_DATEPICKCTRL
|
|
pg->SetPropertyAttribute("DateProperty", wxPG_DATE_PICKER_STYLE,
|
|
(long)(wxDP_DROPDOWN | wxDP_SHOWCENTURY | wxDP_ALLOWNONE));
|
|
|
|
pg->SetPropertyHelpString("DateProperty",
|
|
"Attribute wxPG_DATE_PICKER_STYLE has been set to (long)"
|
|
"(wxDP_DROPDOWN | wxDP_SHOWCENTURY | wxDP_ALLOWNONE).");
|
|
#endif
|
|
|
|
#endif
|
|
|
|
wxPGProperty* carProp = pg->Append(new wxStringProperty("Car", wxPG_LABEL, "<composed>"));
|
|
|
|
pg->AppendIn(carProp, new wxStringProperty("Model", wxPG_LABEL, "Lamborghini Diablo SV"));
|
|
|
|
pg->AppendIn(carProp, new wxIntProperty("Engine Size (cc)", wxPG_LABEL, 5707L));
|
|
|
|
wxPGProperty* speedsProp = pg->AppendIn(carProp, new wxStringProperty("Speeds", wxPG_LABEL, "<composed>"));
|
|
|
|
pg->AppendIn(speedsProp, new wxIntProperty("Max. Speed (mph)", wxPG_LABEL, 290L));
|
|
pg->AppendIn(speedsProp, new wxFloatProperty("0-100 mph (sec)", wxPG_LABEL, 3.9));
|
|
pg->AppendIn(speedsProp, new wxFloatProperty("1/4 mile (sec)", wxPG_LABEL, 8.6));
|
|
|
|
// This is how child property can be referred to by name
|
|
pg->SetPropertyValue("Car.Speeds.Max. Speed (mph)", 300);
|
|
|
|
pg->AppendIn(carProp, new wxIntProperty("Price ($)", wxPG_LABEL, 300000L));
|
|
|
|
pg->AppendIn(carProp, new wxBoolProperty("Convertible", wxPG_LABEL, false));
|
|
|
|
wxPGChoices bc;
|
|
bc.Add("Wee", wxArtProvider::GetBitmap(wxART_CDROM, wxART_OTHER, wxSize(16, 16)));
|
|
bc.Add("Not so wee", wxArtProvider::GetBitmap(wxART_FLOPPY, wxART_OTHER, wxSize(32, 32)));
|
|
bc.Add("Friggin' huge", wxArtProvider::GetBitmap(wxART_HARDDISK, wxART_OTHER, wxSize(64, 64)));
|
|
|
|
pg->Append(new wxEnumProperty("Variable Height Bitmaps", wxPG_LABEL, bc, 0));
|
|
|
|
pid = new wxStringProperty("wxWidgets Traits", wxPG_LABEL, "<composed>");
|
|
pg->SetPropertyReadOnly(pid);
|
|
|
|
pid->AppendChild(new wxStringProperty("Latest Release", wxPG_LABEL, "3.2.1"));
|
|
pid->AppendChild(new wxBoolProperty("Win API", wxPG_LABEL, true));
|
|
|
|
pg->Append(pid);
|
|
|
|
pg->AppendIn(pid, new wxBoolProperty("QT", wxPG_LABEL, true));
|
|
pg->AppendIn(pid, new wxBoolProperty("Cocoa", wxPG_LABEL, true));
|
|
pg->AppendIn(pid, new wxBoolProperty("Haiku", wxPG_LABEL, false));
|
|
pg->AppendIn(pid, new wxStringProperty("Trunk Version", wxPG_LABEL, wxVERSION_NUM_DOT_STRING));
|
|
pg->AppendIn(pid, new wxBoolProperty("GTK+", wxPG_LABEL, true));
|
|
}
|
|
|
|
static wxPropertyGridManager* CreateGrid(int style, int extraStyle)
|
|
{
|
|
// This function creates the property grid in tests
|
|
|
|
if ( style == -1 )
|
|
style = // default style
|
|
wxPG_BOLD_MODIFIED |
|
|
wxPG_SPLITTER_AUTO_CENTER |
|
|
wxPG_AUTO_SORT |
|
|
wxPG_TOOLBAR;
|
|
|
|
if ( extraStyle == -1 )
|
|
// default extra style
|
|
extraStyle = wxPG_EX_MODE_BUTTONS |
|
|
wxPG_EX_MULTIPLE_SELECTION;
|
|
|
|
wxPropertyGridManager* pgManager = new wxPropertyGridManager(wxTheApp->GetTopWindow(), wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
|
|
pgManager->SetSize(wxTheApp->GetTopWindow()->GetClientSize());
|
|
pgManager->SetExtraStyle(extraStyle);
|
|
|
|
// This is the default validation failure behaviour
|
|
pgManager->SetValidationFailureBehavior(wxPGVFBFlags::MarkCell |
|
|
wxPGVFBFlags::ShowMessageBox);
|
|
|
|
wxPropertyGrid* pg = pgManager->GetGrid();
|
|
// Set somewhat different unspecified value appearance
|
|
wxPGCell cell;
|
|
cell.SetText("Unspecified");
|
|
cell.SetFgCol(*wxLIGHT_GREY);
|
|
pg->SetUnspecifiedValueAppearance(cell);
|
|
|
|
// Populate grid
|
|
pgManager->AddPage("Standard Items");
|
|
PopulateWithStandardItems(pgManager);
|
|
pgManager->AddPage("Examples");
|
|
PopulateWithExamples(pgManager);
|
|
|
|
pgManager->Refresh();
|
|
pgManager->Update();
|
|
// Wait for update to be done
|
|
YieldForAWhile(100);
|
|
|
|
return pgManager;
|
|
}
|
|
|
|
static void ReplaceGrid(std::unique_ptr<wxPropertyGridManager>& pgManager, int style, int extraStyle)
|
|
{
|
|
pgManager.reset(); // First destr0y previous instance
|
|
pgManager.reset(CreateGrid(style, extraStyle));
|
|
pgManager->SetFocus();
|
|
}
|
|
|
|
// Callback for testing property sorting
|
|
static int CustomPropertySortFunction(wxPropertyGrid*, wxPGProperty* p1, wxPGProperty* p2)
|
|
{
|
|
// Reverse alphabetical order
|
|
return p2->GetLabel().CmpNoCase(p1->GetBaseName());
|
|
}
|
|
|
|
static std::vector<wxPGProperty*> GetPropertiesInRandomOrder(wxPropertyGridInterface* props, int iterationFlags = wxPG_ITERATE_ALL)
|
|
{
|
|
std::uniform_int_distribution<size_t> distrib(0, 10000);
|
|
std::vector<wxPGProperty*> arr;
|
|
|
|
for ( auto it = props->GetIterator(iterationFlags); !it.AtEnd(); ++it )
|
|
{
|
|
wxPGProperty* p = *it;
|
|
size_t randomNumber = distrib(s_rng);
|
|
p->SetClientData(reinterpret_cast<void*>(randomNumber));
|
|
arr.push_back(p);
|
|
}
|
|
|
|
std::sort(arr.begin(), arr.end(), [](wxPGProperty* p1, wxPGProperty* p2) { return ((size_t)p1->GetClientData()) < ((size_t)p2->GetClientData()); });
|
|
return arr;
|
|
}
|
|
|
|
TEST_CASE("PropertyGridTestCase", "[propgrid]")
|
|
{
|
|
wxTheApp->GetTopWindow()->Raise();
|
|
#if defined(__WXGTK__)
|
|
// Under wxGTK we need to have two children (at least) because if there
|
|
// is one child its paint area is set to fill the whole parent frame.
|
|
std::unique_ptr<wxWindow> win0(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY));
|
|
#endif // wxGTK
|
|
std::unique_ptr<wxPropertyGridManager> pgManager(CreateGrid(-1, -1));
|
|
|
|
SECTION("Iterator")
|
|
{
|
|
// Basic iterator tests
|
|
|
|
int count = 0;
|
|
for ( auto it = pgManager->GetVIterator(wxPG_ITERATE_PROPERTIES); !it.AtEnd(); it.Next() )
|
|
{
|
|
wxPGProperty* p = it.GetProperty();
|
|
if ( p->IsCategory() )
|
|
FAIL_CHECK(wxString::Format("'%s' is a category (non-private child property expected)", p->GetLabel()).c_str());
|
|
else if ( p->GetParent()->HasFlag(wxPGFlags::Aggregate) )
|
|
FAIL_CHECK(wxString::Format("'%s' is a private child (non-private child property expected)", p->GetLabel()).c_str());
|
|
count++;
|
|
}
|
|
INFO(wxString::Format("GetVIterator(wxPG_ITERATE_PROPERTIES) -> %i entries", count).c_str());
|
|
|
|
count = 0;
|
|
for ( auto it = pgManager->GetVIterator(wxPG_ITERATE_CATEGORIES); !it.AtEnd(); it.Next() )
|
|
{
|
|
wxPGProperty* p = it.GetProperty();
|
|
if ( !p->IsCategory() )
|
|
FAIL_CHECK(wxString::Format("'%s' is not a category (only category was expected)", p->GetLabel()).c_str());
|
|
count++;
|
|
}
|
|
INFO(wxString::Format("GetVIterator(wxPG_ITERATE_CATEGORIES) -> %i entries", count).c_str());
|
|
|
|
count = 0;
|
|
for ( auto it = pgManager->GetVIterator(wxPG_ITERATE_PROPERTIES | wxPG_ITERATE_CATEGORIES); !it.AtEnd(); it.Next() )
|
|
{
|
|
wxPGProperty* p = it.GetProperty();
|
|
if ( p->GetParent()->HasFlag(wxPGFlags::Aggregate) )
|
|
FAIL_CHECK(wxString::Format("'%s' is a private child (non-private child property or category expected)", p->GetLabel()).c_str());
|
|
count++;
|
|
}
|
|
INFO(wxString::Format("GetVIterator(wxPG_ITERATE_PROPERTIES|wxPG_ITERATE_CATEGORIES) -> %i entries", count).c_str());
|
|
|
|
count = 0;
|
|
for ( auto it = pgManager->GetVIterator(wxPG_ITERATE_VISIBLE); !it.AtEnd(); it.Next() )
|
|
{
|
|
wxPGProperty* p = it.GetProperty();
|
|
if ( (p->GetParent() != p->GetGrid()->GetRoot() && !p->GetParent()->IsExpanded()) )
|
|
FAIL_CHECK(wxString::Format("'%s' had collapsed parent (only visible properties expected)", p->GetLabel()).c_str());
|
|
else if ( p->HasFlag(wxPGFlags::Hidden) )
|
|
FAIL_CHECK(wxString::Format("'%s' was hidden (only visible properties expected)", p->GetLabel()).c_str());
|
|
count++;
|
|
}
|
|
|
|
INFO(wxString::Format("GetVIterator(wxPG_ITERATE_VISIBLE) -> %i entries", count).c_str());
|
|
}
|
|
|
|
SECTION("Iterator_DeleteFirstPageThenLast")
|
|
{
|
|
// Get all properties from first page
|
|
wxPGVIterator it;
|
|
wxPropertyGridPage* pageFirst = pgManager->GetPage(0);
|
|
std::vector<wxString> propertiesPageFirstInit;
|
|
for ( it = pageFirst->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
propertiesPageFirstInit.push_back(it.GetProperty()->GetName());
|
|
}
|
|
|
|
// Get all properties from last page
|
|
wxPropertyGridPage* pageLast = pgManager->GetPage(pgManager->GetPageCount() - 1);
|
|
std::vector<wxString> propertiesPageLastInit;
|
|
for ( it = pageLast->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
propertiesPageLastInit.push_back(it.GetProperty()->GetName());
|
|
}
|
|
|
|
int countAllPropertiesInit = 0;
|
|
for ( it = pgManager->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
countAllPropertiesInit++;
|
|
}
|
|
|
|
// Delete all properties from first page
|
|
pageFirst->Clear();
|
|
|
|
it = pageFirst->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL));
|
|
REQUIRE(it.AtEnd());
|
|
|
|
std::vector<wxString> propertiesPageLast;
|
|
for ( it = pageLast->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
propertiesPageLast.push_back(it.GetProperty()->GetName());
|
|
}
|
|
REQUIRE(propertiesPageLast == propertiesPageLastInit);
|
|
|
|
size_t countAllProperties = 0;
|
|
for ( it = pgManager->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
countAllProperties++;
|
|
}
|
|
REQUIRE(countAllProperties == countAllPropertiesInit - propertiesPageFirstInit.size());
|
|
|
|
// Delete all properties from last page
|
|
pageLast->Clear();
|
|
|
|
it = pageFirst->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL));
|
|
REQUIRE(it.AtEnd());
|
|
|
|
it = pageLast->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL));
|
|
REQUIRE(it.AtEnd());
|
|
|
|
countAllProperties = 0;
|
|
for ( it = pgManager->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
countAllProperties++;
|
|
}
|
|
REQUIRE(countAllProperties == countAllPropertiesInit - propertiesPageFirstInit.size() - propertiesPageLastInit.size());
|
|
}
|
|
|
|
SECTION("Iterator_DeleteLastPageThenFirst")
|
|
{
|
|
// Get all properties from first page
|
|
wxPGVIterator it;
|
|
wxPropertyGridPage* pageFirst = pgManager->GetPage(0);
|
|
std::vector<wxString> propertiesPageFirstInit;
|
|
for ( it = pageFirst->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
propertiesPageFirstInit.push_back(it.GetProperty()->GetName());
|
|
}
|
|
|
|
// Get all properties from last page
|
|
wxPropertyGridPage* pageLast = pgManager->GetPage(pgManager->GetPageCount() - 1);
|
|
std::vector<wxString> propertiesPageLastInit;
|
|
for ( it = pageLast->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
propertiesPageLastInit.push_back(it.GetProperty()->GetName());
|
|
}
|
|
|
|
int countAllPropertiesInit = 0;
|
|
for ( it = pgManager->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
countAllPropertiesInit++;
|
|
}
|
|
|
|
// Delete all properties from last page
|
|
pageLast->Clear();
|
|
|
|
it = pageLast->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL));
|
|
REQUIRE(it.AtEnd());
|
|
|
|
std::vector<wxString> propertiesPageFirst;
|
|
for ( it = pageFirst->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
propertiesPageFirst.push_back(it.GetProperty()->GetName());
|
|
}
|
|
REQUIRE(propertiesPageFirst == propertiesPageFirstInit);
|
|
|
|
size_t countAllProperties = 0;
|
|
for ( it = pgManager->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
countAllProperties++;
|
|
}
|
|
REQUIRE(countAllProperties == countAllPropertiesInit - propertiesPageLastInit.size());
|
|
|
|
// Delete all properties from first page
|
|
pageFirst->Clear();
|
|
|
|
it = pageFirst->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL));
|
|
REQUIRE(it.AtEnd());
|
|
|
|
it = pageLast->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL));
|
|
REQUIRE(it.AtEnd());
|
|
|
|
countAllProperties = 0;
|
|
for ( it = pgManager->GetVIterator(wxPG_ITERATOR_FLAGS_ALL | wxPG_IT_CHILDREN(wxPG_ITERATOR_FLAGS_ALL)); !it.AtEnd(); it.Next() )
|
|
{
|
|
countAllProperties++;
|
|
}
|
|
REQUIRE(countAllProperties == countAllPropertiesInit - propertiesPageFirstInit.size() - propertiesPageLastInit.size());
|
|
}
|
|
|
|
SECTION("SelectProperty")
|
|
{
|
|
// Test that setting focus to properties does not crash things
|
|
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(i);
|
|
pgManager->SelectPage(page);
|
|
|
|
for ( auto it = page->GetIterator(wxPG_ITERATE_VISIBLE); !it.AtEnd(); ++it )
|
|
{
|
|
wxPGProperty* p = *it;
|
|
INFO(p->GetLabel().c_str());
|
|
pgManager->GetGrid()->SelectProperty(p, true);
|
|
::wxMilliSleep(150);
|
|
wxTheApp->GetTopWindow()->Update();
|
|
}
|
|
}
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("DeleteProperty")
|
|
{
|
|
// Delete everything in reverse order
|
|
|
|
std::vector<wxPGProperty*> array;
|
|
for ( auto it = pgManager->GetVIterator(wxPG_ITERATE_ALL & ~(wxPG_IT_CHILDREN(wxPGFlags::Aggregate))); !it.AtEnd(); it.Next() )
|
|
{
|
|
array.push_back(it.GetProperty());
|
|
}
|
|
|
|
for ( std::vector<wxPGProperty*>::reverse_iterator it2 = array.rbegin(); it2 != array.rend(); ++it2 )
|
|
{
|
|
wxPGProperty* p = *it2;
|
|
INFO(wxString::Format("Deleting '%s' ('%s')", p->GetLabel(), p->GetName()).c_str());
|
|
pgManager->DeleteProperty(p);
|
|
}
|
|
|
|
// Check if grid is empty.
|
|
auto it = pgManager->GetVIterator(wxPG_ITERATE_ALL & ~(wxPG_IT_CHILDREN(wxPGFlags::Aggregate)));
|
|
if ( !it.AtEnd() )
|
|
{
|
|
FAIL_CHECK("Not all properties are deleted");
|
|
}
|
|
|
|
pgManager->Refresh();
|
|
pgManager->Update();
|
|
// Wait for update to be done
|
|
YieldForAWhile(100);
|
|
}
|
|
|
|
SECTION("Default_Values")
|
|
{
|
|
// Test property default values
|
|
|
|
for ( auto it = pgManager->GetVIterator(wxPG_ITERATE_PROPERTIES); !it.AtEnd(); it.Next() )
|
|
{
|
|
wxPGProperty* p = it.GetProperty();
|
|
pgManager->SetPropertyValue(p, p->GetDefaultValue());
|
|
}
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("wxVariant_to_wxAny_conversion")
|
|
{
|
|
// Test wxAny<->wxVariant conversion
|
|
|
|
wxPGProperty* prop;
|
|
wxAny any;
|
|
|
|
#if wxUSE_DATETIME
|
|
prop = pgManager->GetProperty("DateProperty");
|
|
wxDateTime testTime = wxDateTime::Now();
|
|
any = testTime;
|
|
prop->SetValue(any);
|
|
CHECK(prop->GetValue().GetAny().As<wxDateTime>() == testTime);
|
|
#endif
|
|
|
|
prop = pgManager->GetProperty("IntProperty");
|
|
int testInt = 25537983;
|
|
any = testInt;
|
|
prop->SetValue(any);
|
|
CHECK(prop->GetValue().GetAny().As<int>() == testInt);
|
|
CHECK(prop->GetValue().GetAny().As<wxLongLong_t>() == testInt);
|
|
|
|
prop = pgManager->GetProperty("StringProperty");
|
|
wxString testString = "asd934jfyn3";
|
|
any = testString;
|
|
prop->SetValue(any);
|
|
CHECK(prop->GetValue().GetAny().As<wxString>() == testString);
|
|
|
|
// Test with a type generated with IMPLEMENT_VARIANT_OBJECT()
|
|
prop = pgManager->GetProperty("ColourProperty");
|
|
wxColour testCol = *wxCYAN;
|
|
any = testCol;
|
|
prop->SetValue(any);
|
|
CHECK(prop->GetValue().GetAny().As<wxColour>() == testCol);
|
|
}
|
|
|
|
SECTION("GetPropertyValues")
|
|
{
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(i);
|
|
|
|
wxVariant values = page->GetPropertyValues();
|
|
|
|
for ( size_t j = 0; j < values.GetCount(); j++ )
|
|
{
|
|
wxVariant& v = values[j];
|
|
|
|
INFO(wxString::Format("%i: name=\"%s\" type=\"%s\"\n", (int)j,
|
|
v.GetName(), v.GetType()).c_str());
|
|
}
|
|
}
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("SetPropertyValue_and_GetPropertyValue")
|
|
{
|
|
// In this section, mixed up usage of "propname" and "propname"
|
|
// in wxPropertyGridInterface functions is intentional.
|
|
// Purpose is to test wxPGPropArgCls ctors.
|
|
|
|
wxArrayString test_arrstr_1;
|
|
test_arrstr_1.Add("Apple");
|
|
test_arrstr_1.Add("Orange");
|
|
test_arrstr_1.Add("Lemon");
|
|
|
|
wxArrayString test_arrstr_2;
|
|
test_arrstr_2.Add("Potato");
|
|
test_arrstr_2.Add("Cabbage");
|
|
test_arrstr_2.Add("Cucumber");
|
|
|
|
wxArrayInt test_arrint_1;
|
|
test_arrint_1.Add(1);
|
|
test_arrint_1.Add(2);
|
|
test_arrint_1.Add(3);
|
|
|
|
wxArrayInt test_arrint_2;
|
|
test_arrint_2.Add(0);
|
|
test_arrint_2.Add(1);
|
|
test_arrint_2.Add(4);
|
|
|
|
#if wxUSE_DATETIME
|
|
wxDateTime dt1 = wxDateTime::Now();
|
|
if ( dt1.GetMonth() == wxDateTime::Feb && dt1.GetDay() == 29 )
|
|
dt1.SetDay(28);
|
|
|
|
wxDateTime dt2 = dt1;
|
|
dt1.SetYear(dt1.GetYear() - 1);
|
|
dt2.SetYear(dt2.GetYear() - 10);
|
|
#endif
|
|
|
|
pgManager->SetPropertyValue("StringProperty", "Text1");
|
|
pgManager->SetPropertyValue("IntProperty", 1024);
|
|
pgManager->SetPropertyValue("FloatProperty", 1024.0000000001);
|
|
pgManager->SetPropertyValue("BoolProperty", false);
|
|
pgManager->SetPropertyValue("EnumProperty", 120);
|
|
pgManager->SetPropertyValue("ArrayStringProperty", test_arrstr_1);
|
|
wxColour emptyCol;
|
|
pgManager->SetPropertyValue("ColourProperty", emptyCol);
|
|
pgManager->SetPropertyValue("ColourProperty", const_cast<wxObject*>(static_cast<const wxObject*>(wxBLACK)));
|
|
pgManager->SetPropertyValue("MultiChoiceProperty", test_arrint_1);
|
|
#if wxUSE_DATETIME
|
|
pgManager->SetPropertyValue("DateProperty", dt1);
|
|
#endif
|
|
|
|
pgManager->SelectPage(1);
|
|
wxPropertyGrid* pg = pgManager->GetGrid();
|
|
|
|
CHECK(pg->GetPropertyValueAsString("StringProperty") == "Text1");
|
|
CHECK(pg->GetPropertyValueAsInt("IntProperty") == 1024);
|
|
CHECK(pg->GetPropertyValueAsDouble("FloatProperty") == 1024.0000000001);
|
|
CHECK(pg->GetPropertyValueAsBool("BoolProperty") == false);
|
|
CHECK(pg->GetPropertyValueAsLong("EnumProperty") == 120);
|
|
CHECK(pg->GetPropertyValueAsArrayString("ArrayStringProperty") == test_arrstr_1);
|
|
wxColour col;
|
|
col << pgManager->GetPropertyValue("ColourProperty");
|
|
CHECK(col == *wxBLACK);
|
|
CHECK(pg->GetPropertyValueAsArrayInt("MultiChoiceProperty") == test_arrint_1);
|
|
#if wxUSE_DATETIME
|
|
CHECK(pg->GetPropertyValueAsDateTime("DateProperty") == dt1);
|
|
#endif
|
|
|
|
pgManager->SetPropertyValue("IntProperty", wxLL(10000000000));
|
|
CHECK(pg->GetPropertyValueAsLongLong("IntProperty") == wxLL(10000000000));
|
|
|
|
pg->SetPropertyValue("StringProperty", "Text2");
|
|
pg->SetPropertyValue("IntProperty", 512);
|
|
pg->SetPropertyValue("FloatProperty", 512.0);
|
|
pg->SetPropertyValue("BoolProperty", true);
|
|
pg->SetPropertyValue("EnumProperty", 80);
|
|
pg->SetPropertyValue("ArrayStringProperty", test_arrstr_2);
|
|
pg->SetPropertyValue("ColourProperty", const_cast<wxObject*>(static_cast<const wxObject*>(wxWHITE)));
|
|
pg->SetPropertyValue("MultiChoiceProperty", test_arrint_2);
|
|
#if wxUSE_DATETIME
|
|
pg->SetPropertyValue("DateProperty", dt2);
|
|
#endif
|
|
|
|
pgManager->SelectPage(0);
|
|
|
|
CHECK(pgManager->GetPropertyValueAsString("StringProperty") == "Text2");
|
|
CHECK(pgManager->GetPropertyValueAsInt("IntProperty") == 512);
|
|
CHECK(pgManager->GetPropertyValueAsDouble("FloatProperty") == 512.0);
|
|
CHECK(pgManager->GetPropertyValueAsBool("BoolProperty") == true);
|
|
CHECK(pgManager->GetPropertyValueAsLong("EnumProperty") == 80);
|
|
CHECK(pgManager->GetPropertyValueAsArrayString("ArrayStringProperty") == test_arrstr_2);
|
|
col << pgManager->GetPropertyValue("ColourProperty");
|
|
CHECK(col == *wxWHITE);
|
|
CHECK(pgManager->GetPropertyValueAsArrayInt("MultiChoiceProperty") == test_arrint_2);
|
|
#if wxUSE_DATETIME
|
|
CHECK(pgManager->GetPropertyValueAsDateTime("DateProperty") == dt2);
|
|
#endif
|
|
|
|
pgManager->SetPropertyValue("IntProperty", wxLL(-80000000000));
|
|
CHECK(pgManager->GetPropertyValueAsLongLong("IntProperty") == wxLL(-80000000000));
|
|
|
|
wxString nvs = "Lamborghini Diablo XYZ; 5707; [100; 3.9; 8.6] 3000002; Convertible";
|
|
pgManager->SetPropertyValue("Car", nvs);
|
|
|
|
CHECK(pgManager->GetPropertyValueAsString("Car.Model") == "Lamborghini Diablo XYZ");
|
|
CHECK(pgManager->GetPropertyValueAsInt("Car.Speeds.Max. Speed (mph)") == 100);
|
|
CHECK(pgManager->GetPropertyValueAsInt("Car.Price ($)") == 3000002);
|
|
CHECK(pgManager->GetPropertyValueAsBool("Car.Convertible") == true);
|
|
|
|
// SetPropertyValueString for special cases such as wxColour
|
|
pgManager->SetPropertyValueString("ColourProperty", "(123,4,255)");
|
|
col << pgManager->GetPropertyValue("ColourProperty");
|
|
CHECK(col == wxColour(123, 4, 255));
|
|
pgManager->SetPropertyValueString("ColourProperty", "#FE860B");
|
|
col << pgManager->GetPropertyValue("ColourProperty");
|
|
CHECK(col == wxColour(254, 134, 11));
|
|
|
|
pgManager->SetPropertyValueString("ColourPropertyWithAlpha", "(10, 20, 30, 128)");
|
|
col << pgManager->GetPropertyValue("ColourPropertyWithAlpha");
|
|
CHECK(col == wxColour(10, 20, 30, 128));
|
|
CHECK(pgManager->GetPropertyValueAsString("ColourPropertyWithAlpha") == "(10,20,30,128)");
|
|
}
|
|
|
|
SECTION("SetPropertyValueUnspecified")
|
|
{
|
|
// Null variant setter tests
|
|
pgManager->SetPropertyValueUnspecified("StringProperty");
|
|
pgManager->SetPropertyValueUnspecified("IntProperty");
|
|
pgManager->SetPropertyValueUnspecified("FloatProperty");
|
|
pgManager->SetPropertyValueUnspecified("BoolProperty");
|
|
pgManager->SetPropertyValueUnspecified("EnumProperty");
|
|
pgManager->SetPropertyValueUnspecified("ArrayStringProperty");
|
|
pgManager->SetPropertyValueUnspecified("ColourProperty");
|
|
pgManager->SetPropertyValueUnspecified("MultiChoiceProperty");
|
|
#if wxUSE_DATETIME
|
|
pgManager->SetPropertyValueUnspecified("DateProperty");
|
|
#endif
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("Multiple_selection")
|
|
{
|
|
// Test multiple selection
|
|
if ( !(pgManager->GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) )
|
|
ReplaceGrid(pgManager, -1, wxPG_EX_MULTIPLE_SELECTION);
|
|
|
|
wxPropertyGrid* pg = pgManager->GetGrid();
|
|
|
|
wxPGProperty* prop1 = pg->GetProperty("Label");
|
|
wxPGProperty* prop2 = pg->GetProperty("Cell Text Colour");
|
|
wxPGProperty* prop3 = pg->GetProperty("Height");
|
|
wxPGProperty* catProp = pg->GetProperty("Appearance");
|
|
|
|
REQUIRE(prop1);
|
|
REQUIRE(prop2);
|
|
REQUIRE(prop3);
|
|
|
|
pg->ClearSelection();
|
|
pg->AddToSelection(prop1);
|
|
pg->AddToSelection(prop2);
|
|
pg->AddToSelection(prop3);
|
|
|
|
// Adding category to selection should fail silently
|
|
pg->AddToSelection(catProp);
|
|
|
|
wxArrayPGProperty selectedProperties = pg->GetSelectedProperties();
|
|
|
|
CHECK(selectedProperties.size() == 3);
|
|
CHECK(pg->IsPropertySelected(prop1));
|
|
CHECK(pg->IsPropertySelected(prop2));
|
|
CHECK(pg->IsPropertySelected(prop3));
|
|
CHECK_FALSE(pg->IsPropertySelected(catProp));
|
|
|
|
pg->RemoveFromSelection(prop1);
|
|
wxArrayPGProperty selectedProperties2 = pg->GetSelectedProperties();
|
|
|
|
CHECK(selectedProperties2.size() == 2);
|
|
CHECK_FALSE(pg->IsPropertySelected(prop1));
|
|
CHECK(pg->IsPropertySelected(prop2));
|
|
CHECK(pg->IsPropertySelected(prop3));
|
|
|
|
pg->ClearSelection();
|
|
|
|
wxArrayPGProperty selectedProperties3 = pg->GetSelectedProperties();
|
|
|
|
CHECK(selectedProperties3.size() == 0);
|
|
CHECK_FALSE(pg->IsPropertySelected(prop1));
|
|
CHECK_FALSE(pg->IsPropertySelected(prop2));
|
|
CHECK_FALSE(pg->IsPropertySelected(prop3));
|
|
|
|
pg->SelectProperty(prop2);
|
|
|
|
CHECK_FALSE(pg->IsPropertySelected(prop1));
|
|
CHECK(pg->IsPropertySelected(prop2));
|
|
CHECK_FALSE(pg->IsPropertySelected(prop3));
|
|
}
|
|
|
|
SECTION("GetMainParent")
|
|
{
|
|
// Test retrieving main parent of the property
|
|
|
|
// Simple properties
|
|
wxPGProperty* prop = pgManager->GetProperty("DateProperty");
|
|
wxPGProperty* parent = prop->GetMainParent();
|
|
CHECK(parent->GetName() == "DateProperty");
|
|
|
|
prop = pgManager->GetProperty("Label");
|
|
parent = prop->GetMainParent();
|
|
CHECK(parent->GetName() == "Label");
|
|
|
|
// Properties with children
|
|
prop = pgManager->GetProperty("Font");
|
|
REQUIRE(prop);
|
|
parent = prop->GetMainParent();
|
|
REQUIRE(parent);
|
|
CHECK(parent->GetName() == "Font");
|
|
|
|
prop = pgManager->GetProperty("Font.Style");
|
|
REQUIRE(prop);
|
|
parent = prop->GetMainParent();
|
|
REQUIRE(parent);
|
|
CHECK(parent->GetName() == "Font");
|
|
|
|
prop = pgManager->GetProperty("Car");
|
|
REQUIRE(prop);
|
|
parent = prop->GetMainParent();
|
|
REQUIRE(parent);
|
|
CHECK(parent->GetName() == "Car");
|
|
|
|
prop = pgManager->GetProperty("Car.Model");
|
|
REQUIRE(prop);
|
|
parent = prop->GetMainParent();
|
|
REQUIRE(parent);
|
|
CHECK(parent->GetName() == "Car");
|
|
|
|
prop = pgManager->GetProperty("Car.Speeds");
|
|
REQUIRE(prop);
|
|
parent = prop->GetMainParent();
|
|
REQUIRE(parent);
|
|
CHECK(parent->GetName() == "Car");
|
|
}
|
|
|
|
SECTION("Label_editing")
|
|
{
|
|
// Test label editing
|
|
|
|
wxPropertyGrid* pg = pgManager->GetGrid();
|
|
|
|
// Just mostly test that these won't crash
|
|
pg->MakeColumnEditable(0, true);
|
|
pg->MakeColumnEditable(2, true);
|
|
pg->MakeColumnEditable(0, false);
|
|
pg->MakeColumnEditable(2, false);
|
|
pg->SelectProperty("Height");
|
|
pg->BeginLabelEdit(0);
|
|
pg->BeginLabelEdit(0);
|
|
pg->EndLabelEdit(0);
|
|
pg->EndLabelEdit(0);
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("Attributes")
|
|
{
|
|
wxPGProperty* prop = pgManager->GetProperty("StringProperty");
|
|
prop->SetAttribute("Dummy Attribute", 15L);
|
|
|
|
CHECK(prop->GetAttribute("Dummy Attribute").GetLong() == 15L);
|
|
|
|
prop->SetAttribute("Dummy Attribute", wxVariant());
|
|
|
|
CHECK(prop->GetAttribute("Dummy Attribute").IsNull());
|
|
}
|
|
|
|
SECTION("Attributes_with_PGManager")
|
|
{
|
|
const long val = 25;
|
|
pgManager->SetPropertyAttribute("IntProperty", "Dummy Attribute", val);
|
|
CHECK(pgManager->GetPropertyAttribute("IntProperty", "Dummy Attribute").GetLong() == val);
|
|
|
|
pgManager->SetPropertyAttribute("IntProperty", "Dummy Attribute", wxVariant());
|
|
CHECK(pgManager->GetPropertyAttribute("IntProperty", "Dummy Attribute").IsNull());
|
|
}
|
|
|
|
SECTION("Getting_list_of_attributes")
|
|
{
|
|
wxPGProperty* prop = pgManager->GetProperty("Height");
|
|
const wxPGAttributeStorage& attrs1 = prop->GetAttributes();
|
|
CHECK(attrs1.GetCount() >= 1);
|
|
|
|
const wxPGAttributeStorage& attrs2 = pgManager->GetPropertyAttributes("Height");
|
|
CHECK(attrs2.GetCount() == attrs1.GetCount());
|
|
|
|
// Compare both lists
|
|
wxVariant val1;
|
|
wxVariant val2;
|
|
wxPGAttributeStorage::const_iterator it = attrs1.StartIteration();
|
|
while ( attrs1.GetNext(it, val1) )
|
|
{
|
|
val2 = attrs2.FindValue(val1.GetName());
|
|
CHECK(val1 == val2);
|
|
}
|
|
}
|
|
|
|
SECTION("Copying_list_of_attributes")
|
|
{
|
|
wxPGAttributeStorage attrs1(pgManager->GetPropertyAttributes("Height"));
|
|
CHECK(attrs1.GetCount() >= 1);
|
|
|
|
wxPGAttributeStorage attrs2;
|
|
attrs2 = attrs1;
|
|
CHECK(attrs2.GetCount() == attrs1.GetCount());
|
|
|
|
// Compare both lists
|
|
wxVariant val1;
|
|
wxVariant val2;
|
|
wxPGAttributeStorage::const_iterator it = attrs1.StartIteration();
|
|
while ( attrs1.GetNext(it, val1) )
|
|
{
|
|
val2 = attrs2.FindValue(val1.GetName());
|
|
CHECK(val1 == val2);
|
|
}
|
|
}
|
|
|
|
SECTION("MaxLength")
|
|
{
|
|
wxPGProperty* prop1 = pgManager->GetProperty("StringProperty");
|
|
wxString propSetValStr = "12345678901234567890";
|
|
prop1->SetValueFromString(propSetValStr);
|
|
CHECK(prop1->SetMaxLength(10));
|
|
CHECK(prop1->GetMaxLength() == 10);
|
|
wxString propGetValStr = prop1->GetValueAsString();
|
|
CHECK(propGetValStr == propSetValStr);
|
|
prop1->SetValueFromString(propSetValStr);
|
|
propGetValStr = prop1->GetValueAsString();
|
|
CHECK(propGetValStr == propSetValStr);
|
|
|
|
CHECK(prop1->SetMaxLength(-1));
|
|
CHECK(prop1->GetMaxLength() == 0);
|
|
propGetValStr = prop1->GetValueAsString();
|
|
CHECK(propGetValStr == propSetValStr);
|
|
|
|
wxPGProperty* prop2 = pgManager->GetProperty("LongStringProp");
|
|
propSetValStr = "123456789012345678901234567890";
|
|
prop2->SetValueFromString(propSetValStr);
|
|
CHECK(prop2->SetMaxLength(20));
|
|
CHECK(prop2->GetMaxLength() == 20);
|
|
propGetValStr = prop2->GetValueAsString();
|
|
CHECK(propGetValStr == propSetValStr);
|
|
prop2->SetValueFromString(propSetValStr);
|
|
propGetValStr = prop2->GetValueAsString();
|
|
CHECK(propGetValStr == propSetValStr);
|
|
|
|
wxPGProperty* prop3 = pgManager->GetProperty("IntProperty");
|
|
const long propSetValInt = 1234567;
|
|
prop3->SetValueFromInt(propSetValInt);
|
|
CHECK(prop3->SetMaxLength(4));
|
|
CHECK(prop3->GetMaxLength() == 4);
|
|
int propGetValInt = prop3->GetValue().GetLong();
|
|
CHECK(propGetValInt == propSetValInt);
|
|
prop3->SetValueFromInt(propSetValInt);
|
|
propGetValInt = prop3->GetValue().GetLong();
|
|
CHECK(propGetValInt == propSetValInt);
|
|
|
|
wxPGProperty* prop4 = pgManager->GetProperty("ArrayStringProperty");
|
|
const wxString arrStr[3]{ "01234567890", "abcdefghijk", "ABCDEFGHIJK" };
|
|
wxArrayString propSetValArrStr(WXSIZEOF(arrStr), arrStr);
|
|
prop4->SetValue(wxVariant(propSetValArrStr));
|
|
CHECK(prop4->SetMaxLength(25));
|
|
CHECK(prop4->GetMaxLength() == 25);
|
|
wxArrayString propGetValArrStr = prop4->GetValue().GetArrayString();
|
|
CHECK(propGetValArrStr == propSetValArrStr);
|
|
prop4->SetValueFromString(wxVariant(propSetValArrStr));
|
|
propGetValStr = prop4->GetValueAsString();
|
|
CHECK(propGetValArrStr == propSetValArrStr);
|
|
|
|
wxPGProperty* prop5 = pgManager->GetProperty("EnumProperty");
|
|
CHECK_FALSE(prop5->SetMaxLength(50));
|
|
|
|
wxPGProperty* prop6 = pgManager->GetProperty("BoolProperty");
|
|
CHECK_FALSE(prop6->SetMaxLength(60));
|
|
}
|
|
|
|
SECTION("MaxLength_with_PG")
|
|
{
|
|
pgManager->SelectPage(1);
|
|
wxPropertyGrid* pg = pgManager->GetGrid();
|
|
|
|
wxPGProperty* prop1 = pgManager->GetProperty("StringProperty");
|
|
wxString propSetValStr = "12345678901234567890";
|
|
pg->SetPropertyValue(prop1, propSetValStr);
|
|
CHECK(pg->SetPropertyMaxLength("StringProperty", 15));
|
|
CHECK(prop1->GetMaxLength() == 15);
|
|
wxString propGetValStr = pg->GetPropertyValueAsString(prop1);
|
|
CHECK(propGetValStr == propSetValStr);
|
|
pg->SetPropertyValue(prop1, propSetValStr);
|
|
propGetValStr = pg->GetPropertyValueAsString(prop1);
|
|
CHECK(propGetValStr == propSetValStr);
|
|
|
|
CHECK(pg->SetPropertyMaxLength("StringProperty", -1));
|
|
CHECK(prop1->GetMaxLength() == 0);
|
|
propGetValStr = pg->GetPropertyValueAsString(prop1);
|
|
CHECK(propGetValStr == propSetValStr);
|
|
|
|
wxPGProperty* prop2 = pgManager->GetProperty("LongStringProp");
|
|
propSetValStr = "123456789012345678901234567890";
|
|
pg->SetPropertyValue(prop2, propSetValStr);
|
|
CHECK(pg->SetPropertyMaxLength("LongStringProp", 25));
|
|
CHECK(prop2->GetMaxLength() == 25);
|
|
propGetValStr = pg->GetPropertyValueAsString(prop2);
|
|
CHECK(propGetValStr == propSetValStr);
|
|
pg->SetPropertyValue(prop2, propSetValStr);
|
|
propGetValStr = pg->GetPropertyValueAsString(prop2);
|
|
CHECK(propGetValStr == propSetValStr);
|
|
|
|
wxPGProperty* prop3 = pgManager->GetProperty("FloatProperty");
|
|
double propSetValFloat = 1234.567;
|
|
pg->SetPropertyValue(prop3, propSetValFloat);
|
|
CHECK(pg->SetPropertyMaxLength("FloatProperty", 5));
|
|
CHECK(prop3->GetMaxLength() == 5);
|
|
double propGetValFloat = pg->GetPropertyValueAsDouble(prop3);
|
|
CHECK(propGetValFloat == propSetValFloat);
|
|
|
|
CHECK(pg->SetPropertyMaxLength("FloatProperty", -1));
|
|
CHECK(prop3->GetMaxLength() == 0);
|
|
propGetValFloat = pg->GetPropertyValueAsDouble(prop3);
|
|
CHECK(propGetValFloat == propSetValFloat);
|
|
|
|
CHECK_FALSE(pg->SetPropertyMaxLength("ColourProperty", 35));
|
|
|
|
CHECK_FALSE(pg->SetPropertyMaxLength("BoolProperty", 3));
|
|
}
|
|
|
|
#if WXWIN_COMPATIBILITY_3_0
|
|
SECTION("DoubleToString")
|
|
{
|
|
// Locale-specific decimal separator
|
|
wxString sep = wxString::Format("%g", 1.1)[1];
|
|
|
|
wxString s;
|
|
|
|
CHECK(wxPropertyGrid::DoubleToString(s, 123.123, 2, true) ==
|
|
wxString::Format("123%s12", sep));
|
|
CHECK(wxPropertyGrid::DoubleToString(s, -123.123, 4, false) ==
|
|
wxString::Format("-123%s1230", sep));
|
|
CHECK(wxPropertyGrid::DoubleToString(s, -0.02, 1, false) ==
|
|
wxString::Format("0%s0", sep));
|
|
CHECK(wxPropertyGrid::DoubleToString(s, -0.000123, 3, true) == "0");
|
|
}
|
|
#endif
|
|
|
|
SECTION("GetPropertyValues")
|
|
{
|
|
wxPropertyGridPage* page1 = pgManager->GetPage(0);
|
|
wxVariant pg1_values = page1->GetPropertyValues("Page1", nullptr, wxPGPropertyValuesFlags::KeepStructure);
|
|
wxPropertyGridPage* page2 = pgManager->GetPage(1);
|
|
wxVariant pg2_values = page2->GetPropertyValues("Page2", nullptr, wxPGPropertyValuesFlags::KeepStructure);
|
|
SUCCEED();
|
|
|
|
SECTION("SetPropertyValues")
|
|
{
|
|
page1->SetPropertyValues(pg2_values);
|
|
page2->SetPropertyValues(pg1_values);
|
|
SUCCEED();
|
|
}
|
|
}
|
|
|
|
SECTION("Collapse_and_GetFirstCategory_and_GetNextCategory")
|
|
{
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(i);
|
|
|
|
for ( auto it = page->GetIterator(wxPG_ITERATE_CATEGORIES); !it.AtEnd(); ++it )
|
|
{
|
|
wxPGProperty* p = *it;
|
|
|
|
CHECK(page->IsPropertyCategory(p));
|
|
|
|
INFO(wxString::Format("Collapsing: %s\n", page->GetPropertyLabel(p)).c_str());
|
|
page->Collapse(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("Save_And_RestoreEditableState")
|
|
{
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
pgManager->SelectPage(i);
|
|
|
|
wxString stringState = pgManager->SaveEditableState();
|
|
CHECK(pgManager->RestoreEditableState(stringState));
|
|
}
|
|
}
|
|
|
|
SECTION("Expand_and_GetFirstCategory_and_GetNextCategory")
|
|
{
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(i);
|
|
|
|
for ( auto it = page->GetIterator(wxPG_ITERATE_CATEGORIES); !it.AtEnd(); ++it )
|
|
{
|
|
wxPGProperty* p = *it;
|
|
|
|
CHECK(page->IsPropertyCategory(p));
|
|
|
|
INFO(wxString::Format("Expand: %s\n", page->GetPropertyLabel(p)).c_str());
|
|
page->Expand(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("Choice_Manipulation")
|
|
{
|
|
wxPGProperty* enumProp = pgManager->GetProperty("EnumProperty");
|
|
|
|
pgManager->SelectPage(1);
|
|
pgManager->SelectProperty(enumProp);
|
|
REQUIRE(pgManager->GetGrid()->GetSelection() == enumProp);
|
|
|
|
const wxPGChoices& choices = enumProp->GetChoices();
|
|
int ind = enumProp->InsertChoice("New Choice", choices.GetCount() / 2);
|
|
enumProp->DeleteChoice(ind);
|
|
SUCCEED();
|
|
}
|
|
|
|
//if ( !pgman->HasFlag(wxPG_HIDE_CATEGORIES) )
|
|
SECTION("RandomCollapse")
|
|
{
|
|
// Select the most error prone page as visible.
|
|
pgManager->SelectPage(1);
|
|
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(i);
|
|
|
|
std::vector<wxPGProperty*> arr;
|
|
for ( auto it = page->GetIterator(wxPG_ITERATE_CATEGORIES); !it.AtEnd(); ++it )
|
|
{
|
|
arr.push_back(*it);
|
|
}
|
|
|
|
if ( !arr.empty() )
|
|
{
|
|
pgManager->Collapse(arr[0]);
|
|
|
|
for ( size_t n = arr.size() - 1; n > 0; n-- )
|
|
{
|
|
pgManager->Collapse(arr[n]);
|
|
}
|
|
}
|
|
}
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("EnsureVisible")
|
|
{
|
|
pgManager->EnsureVisible("Cell Colour");
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("RemoveProperty")
|
|
{
|
|
wxPGProperty* p;
|
|
|
|
wxPGProperty* origParent = pgManager->GetProperty("Window Styles")->GetParent();
|
|
|
|
// For testing purposes, let's set some custom cell colours
|
|
p = pgManager->GetProperty("Window Styles");
|
|
p->SetCell(2, wxPGCell("style"));
|
|
p = pgManager->RemoveProperty("Window Styles");
|
|
pgManager->Refresh();
|
|
pgManager->Update();
|
|
|
|
pgManager->AppendIn(origParent, p);
|
|
CHECK(p->GetCell(2).GetText() == "style");
|
|
pgManager->Refresh();
|
|
pgManager->Update();
|
|
}
|
|
|
|
SECTION("SortFunction")
|
|
{
|
|
wxPGProperty* p;
|
|
|
|
// Make sure indexes are as supposed
|
|
p = pgManager->GetProperty("User Name");
|
|
CHECK(p->GetIndexInParent() == 3);
|
|
|
|
p = pgManager->GetProperty("User Id");
|
|
CHECK(p->GetIndexInParent() == 2);
|
|
|
|
p = pgManager->GetProperty("User Home");
|
|
CHECK(p->GetIndexInParent() == 1);
|
|
|
|
p = pgManager->GetProperty("Operating System");
|
|
CHECK(p->GetIndexInParent() == 0);
|
|
|
|
pgManager->GetGrid()->SetSortFunction(CustomPropertySortFunction);
|
|
|
|
pgManager->GetGrid()->SortChildren("Environment");
|
|
|
|
// Make sure indexes have been reversed
|
|
p = pgManager->GetProperty("User Name");
|
|
CHECK(p->GetIndexInParent() == 0);
|
|
|
|
p = pgManager->GetProperty("User Id");
|
|
CHECK(p->GetIndexInParent() == 1);
|
|
|
|
p = pgManager->GetProperty("User Home");
|
|
CHECK(p->GetIndexInParent() == 2);
|
|
|
|
p = pgManager->GetProperty("Operating System");
|
|
CHECK(p->GetIndexInParent() == 3);
|
|
}
|
|
|
|
SECTION("Clear_with_PGManager")
|
|
{
|
|
// Manager clear
|
|
pgManager->SelectProperty("Label");
|
|
pgManager->Clear();
|
|
|
|
CHECK(pgManager->GetPageCount() == 0);
|
|
|
|
CHECK_FALSE(pgManager->GetGrid()->GetRoot()->HasAnyChild());
|
|
}
|
|
|
|
SECTION("Clear_with_PG")
|
|
{
|
|
// Grid clear
|
|
pgManager->SelectProperty("Label");
|
|
pgManager->GetGrid()->Clear();
|
|
|
|
CHECK_FALSE(pgManager->GetGrid()->GetRoot()->HasAnyChild());
|
|
}
|
|
|
|
SECTION("SetPropertyBackgroundColour")
|
|
{
|
|
wxPropertyGrid* pg = pgManager->GetGrid();
|
|
REQUIRE(pg->GetPropertyByName("Appearance"));
|
|
REQUIRE(pg->GetPropertyByName("PositionCategory"));
|
|
REQUIRE(pg->GetPropertyByName("Environment"));
|
|
REQUIRE(pg->GetPropertyByName("More Examples"));
|
|
|
|
pgManager->Freeze();
|
|
// Set custom colours.
|
|
pg->SetPropertyTextColour("Appearance", wxColour(255, 0, 0), wxPGPropertyValuesFlags::DontRecurse);
|
|
pg->SetPropertyBackgroundColour("Appearance", wxColour(255, 255, 183));
|
|
pg->SetPropertyTextColour("Appearance", wxColour(255, 0, 183));
|
|
pg->SetPropertyTextColour("PositionCategory", wxColour(0, 255, 0), wxPGPropertyValuesFlags::DontRecurse);
|
|
pg->SetPropertyBackgroundColour("PositionCategory", wxColour(255, 226, 190));
|
|
pg->SetPropertyTextColour("PositionCategory", wxColour(255, 0, 190));
|
|
pg->SetPropertyTextColour("Environment", wxColour(0, 0, 255), wxPGPropertyValuesFlags::DontRecurse);
|
|
pg->SetPropertyBackgroundColour("Environment", wxColour(208, 240, 175));
|
|
pg->SetPropertyTextColour("Environment", wxColour(255, 255, 255));
|
|
pg->SetPropertyBackgroundColour("More Examples", wxColour(172, 237, 255));
|
|
pg->SetPropertyTextColour("More Examples", wxColour(172, 0, 255));
|
|
pgManager->Thaw();
|
|
pgManager->Refresh();
|
|
|
|
wxColour my_grey_1(212, 208, 200);
|
|
wxColour my_grey_2(241, 239, 226);
|
|
wxColour my_grey_3(113, 111, 100);
|
|
pgManager->Freeze();
|
|
pgManager->GetGrid()->SetMarginColour(*wxWHITE);
|
|
pgManager->GetGrid()->SetCaptionBackgroundColour(*wxWHITE);
|
|
pgManager->GetGrid()->SetCellBackgroundColour(my_grey_2);
|
|
pgManager->GetGrid()->SetCellBackgroundColour(my_grey_2);
|
|
pgManager->GetGrid()->SetCellTextColour(my_grey_3);
|
|
pgManager->GetGrid()->SetLineColour(my_grey_1);
|
|
pgManager->Thaw();
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("SetSplitterPosition")
|
|
{
|
|
#ifndef __WXQT__
|
|
const int trySplitterPos = wxTheApp->GetTopWindow()->FromDIP(50);
|
|
#else
|
|
const int trySplitterPos = 51; // FIXME!
|
|
#endif
|
|
int style = wxPG_AUTO_SORT; // wxPG_SPLITTER_AUTO_CENTER;
|
|
ReplaceGrid(pgManager, style, -1);
|
|
|
|
pgManager->SetSplitterPosition(trySplitterPos);
|
|
|
|
CHECK(pgManager->GetGrid()->GetSplitterPosition() == trySplitterPos);
|
|
|
|
wxSize origSz = wxTheApp->GetTopWindow()->GetSize();
|
|
|
|
wxSize sz = origSz;
|
|
sz.IncBy(5, 5);
|
|
wxTheApp->GetTopWindow()->SetSize(sz);
|
|
|
|
CHECK(pgManager->GetGrid()->GetSplitterPosition() == trySplitterPos);
|
|
|
|
wxTheApp->GetTopWindow()->SetSize(origSz);
|
|
}
|
|
|
|
SECTION("HideProperty")
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(0);
|
|
|
|
std::vector<wxPGProperty*> arr1 = GetPropertiesInRandomOrder(page);
|
|
for ( size_t i = 0; i < arr1.size(); i++ )
|
|
{
|
|
wxPGProperty* p = arr1[i];
|
|
page->HideProperty(p, true);
|
|
|
|
INFO(wxString::Format("HideProperty(%i, %s)", (int)i, p->GetLabel()).c_str());
|
|
unsigned int h1 = page->GetVirtualHeight();
|
|
unsigned int h2 = page->GetActualVirtualHeight();
|
|
REQUIRE(h1 == h2);
|
|
}
|
|
|
|
std::vector<wxPGProperty*> arr2 = GetPropertiesInRandomOrder(page);
|
|
for ( size_t i = 0; i < arr2.size(); i++ )
|
|
{
|
|
wxPGProperty* p = arr2[i];
|
|
page->HideProperty(p, false);
|
|
|
|
INFO(wxString::Format("ShowProperty(%i, %s)", (int)i, p->GetLabel()).c_str());
|
|
unsigned int h1 = page->GetVirtualHeight();
|
|
unsigned int h2 = page->GetActualVirtualHeight();
|
|
REQUIRE(h1 == h2);
|
|
}
|
|
|
|
//
|
|
// Let's do some more, for better consistency
|
|
arr1 = GetPropertiesInRandomOrder(page);
|
|
for ( size_t i = 0; i < arr1.size(); i++ )
|
|
{
|
|
wxPGProperty* p = arr1[i];
|
|
page->HideProperty(p, true);
|
|
|
|
INFO(wxString::Format("HideProperty(%i, %s)", (int)i, p->GetLabel()).c_str());
|
|
unsigned int h1 = page->GetVirtualHeight();
|
|
unsigned int h2 = page->GetActualVirtualHeight();
|
|
REQUIRE(h1 == h2);
|
|
}
|
|
|
|
arr2 = GetPropertiesInRandomOrder(page);
|
|
for ( size_t i = 0; i < arr2.size(); i++ )
|
|
{
|
|
wxPGProperty* p = arr2[i];
|
|
page->HideProperty(p, false);
|
|
|
|
INFO(wxString::Format("ShowProperty(%i, %s)", (int)i, p->GetLabel()).c_str());
|
|
unsigned int h1 = page->GetVirtualHeight();
|
|
unsigned int h2 = page->GetActualVirtualHeight();
|
|
REQUIRE(h1 == h2);
|
|
}
|
|
|
|
// Ok, this time only hide half of them
|
|
arr1 = GetPropertiesInRandomOrder(page);
|
|
arr1.resize(arr1.size() / 2);
|
|
for ( size_t i = 0; i < arr1.size(); i++ )
|
|
{
|
|
wxPGProperty* p = arr1[i];
|
|
page->HideProperty(p, true);
|
|
|
|
INFO(wxString::Format("HideProperty(%i, %s)", (int)i, p->GetLabel()).c_str());
|
|
unsigned int h1 = page->GetVirtualHeight();
|
|
unsigned int h2 = page->GetActualVirtualHeight();
|
|
REQUIRE(h1 == h2);
|
|
}
|
|
|
|
arr2 = GetPropertiesInRandomOrder(page);
|
|
for ( size_t i = 0; i < arr2.size(); i++ )
|
|
{
|
|
wxPGProperty* p = arr2[i];
|
|
page->HideProperty(p, false);
|
|
|
|
INFO(wxString::Format("ShowProperty(%i, %s)", (int)i, p->GetLabel()).c_str());
|
|
unsigned int h1 = page->GetVirtualHeight();
|
|
unsigned int h2 = page->GetActualVirtualHeight();
|
|
REQUIRE(h1 == h2);
|
|
}
|
|
}
|
|
|
|
SECTION("SetFlagsAsString_GetFlagsAsString")
|
|
{
|
|
std::uniform_int_distribution<int> distrib(0, 1);
|
|
|
|
// Select the most error prone page as visible.
|
|
pgManager->SelectPage(1);
|
|
|
|
for ( size_t i = 0; i < pgManager->GetPageCount(); i++ )
|
|
{
|
|
wxPropertyGridPage* page = pgManager->GetPage(i);
|
|
|
|
for ( auto it = page->GetIterator(wxPG_ITERATE_VISIBLE); !it.AtEnd(); ++it )
|
|
{
|
|
wxPGProperty* p = *it;
|
|
|
|
// Save initial flags
|
|
wxPGFlags oldFlags = wxPGFlags::Null;
|
|
if ( p->HasFlag(wxPGFlags::Collapsed) )
|
|
{
|
|
oldFlags |= wxPGFlags::Collapsed;
|
|
}
|
|
if ( p->HasFlag(wxPGFlags::Disabled) )
|
|
{
|
|
oldFlags |= wxPGFlags::Disabled;
|
|
}
|
|
if ( p->HasFlag(wxPGFlags::Hidden) )
|
|
{
|
|
oldFlags |= wxPGFlags::Hidden;
|
|
}
|
|
if ( p->HasFlag(wxPGFlags::NoEditor) )
|
|
{
|
|
oldFlags |= wxPGFlags::NoEditor;
|
|
}
|
|
|
|
wxString flags;
|
|
|
|
if ( p->IsCategory() )
|
|
{
|
|
if ( distrib(s_rng) != 0 ) // random Boolean value
|
|
{
|
|
if ( !flags.empty() )
|
|
{
|
|
flags.append("|");
|
|
}
|
|
flags.append("COLLAPSED");
|
|
}
|
|
}
|
|
|
|
if ( distrib(s_rng) != 0 ) // random Boolean value
|
|
{
|
|
if ( !flags.empty() )
|
|
{
|
|
flags.append("|");
|
|
}
|
|
flags.append("DISABLED");
|
|
}
|
|
|
|
if ( distrib(s_rng) != 0 ) // random Boolean value
|
|
{
|
|
if ( !flags.empty() )
|
|
{
|
|
flags.append("|");
|
|
}
|
|
flags.append("HIDDEN");
|
|
}
|
|
|
|
// Set flags
|
|
p->SetFlagsFromString(flags);
|
|
|
|
// Verify if flags have been properly set
|
|
if ( flags.Find("COLLAPSED") != wxNOT_FOUND &&
|
|
!p->HasFlag(wxPGFlags::Collapsed) )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Error setting flag from string 'COLLAPSED' for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
if ( flags.Find("COLLAPSED") == wxNOT_FOUND &&
|
|
p->HasFlag(wxPGFlags::Collapsed) )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Error resetting flag from string 'COLLAPSED'for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
if ( flags.Find("DISABLED") != wxNOT_FOUND &&
|
|
!p->HasFlag(wxPGFlags::Disabled) )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Error setting flag from string 'DISABLED' for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
if ( flags.Find("DISABLED") == wxNOT_FOUND &&
|
|
p->HasFlag(wxPGFlags::Disabled) )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Error resetting flag from string 'DISABLED' for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
if ( flags.Find("HIDDEN") != wxNOT_FOUND &&
|
|
!p->HasFlag(wxPGFlags::Hidden) )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Error setting flag from string 'HIDDEN' for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
if ( flags.Find("HIDDEN") == wxNOT_FOUND &&
|
|
p->HasFlag(wxPGFlags::Hidden) )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Error resetting flag from string 'HIDDEN' for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
// Get individual flags
|
|
bool ok;
|
|
|
|
flags = p->GetFlagsAsString(wxPGFlags::Collapsed);
|
|
if ( p->HasFlag(wxPGFlags::Collapsed) )
|
|
{
|
|
ok = (flags == "COLLAPSED");
|
|
}
|
|
else
|
|
{
|
|
ok = flags.empty();
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::Collapsed flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
flags = p->GetFlagsAsString(wxPGFlags::Disabled);
|
|
if ( p->HasFlag(wxPGFlags::Disabled) )
|
|
{
|
|
ok = (flags == "DISABLED");
|
|
}
|
|
else
|
|
{
|
|
ok = flags.empty();
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::Disabled flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
flags = p->GetFlagsAsString(wxPGFlags::Hidden);
|
|
if ( p->HasFlag(wxPGFlags::Hidden) )
|
|
{
|
|
ok = (flags == "HIDDEN");
|
|
}
|
|
else
|
|
{
|
|
ok = flags.empty();
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::Hidden flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
flags = p->GetFlagsAsString(wxPGFlags::NoEditor);
|
|
if ( p->HasFlag(wxPGFlags::NoEditor) )
|
|
{
|
|
ok = (flags == "NOEDITOR");
|
|
}
|
|
else
|
|
{
|
|
ok = flags.empty();
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::NoEditor flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
// Get all flags
|
|
flags = p->GetFlagsAsString(wxPGFlags::StringStoredFlags);
|
|
if ( p->HasFlag(wxPGFlags::Collapsed) )
|
|
{
|
|
ok = (flags.Find("COLLAPSED") != wxNOT_FOUND);
|
|
}
|
|
else
|
|
{
|
|
ok = (flags.Find("COLLAPSED") == wxNOT_FOUND);
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::Collapsed flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
if ( p->HasFlag(wxPGFlags::Disabled) )
|
|
{
|
|
ok = (flags.Find("DISABLED") != wxNOT_FOUND);
|
|
}
|
|
else
|
|
{
|
|
ok = (flags.Find("DISABLED") == wxNOT_FOUND);
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::Disabled flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
if ( p->HasFlag(wxPGFlags::Hidden) )
|
|
{
|
|
ok = (flags.Find("HIDDEN") != wxNOT_FOUND);
|
|
}
|
|
else
|
|
{
|
|
ok = (flags.Find("HIDDEN") == wxNOT_FOUND);
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::Hidden flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
if ( p->HasFlag(wxPGFlags::NoEditor) )
|
|
{
|
|
ok = (flags.Find("NOEDITOR") != wxNOT_FOUND);
|
|
}
|
|
else
|
|
{
|
|
ok = (flags.Find("NOEDITOR") == wxNOT_FOUND);
|
|
}
|
|
if ( !ok )
|
|
{
|
|
FAIL_CHECK(wxString::Format("Invalid string for wxPGFlags::NoEditor flag for property '%s'",
|
|
p->GetName()).c_str());
|
|
}
|
|
|
|
// Restore original flags
|
|
p->ChangeFlag(wxPGFlags::Collapsed, !!(oldFlags & wxPGFlags::Collapsed));
|
|
p->ChangeFlag(wxPGFlags::Disabled, !!(oldFlags & wxPGFlags::Disabled));
|
|
p->ChangeFlag(wxPGFlags::Hidden, !!(oldFlags & wxPGFlags::Hidden));
|
|
p->ChangeFlag(wxPGFlags::NoEditor, !!(oldFlags & wxPGFlags::NoEditor));
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("MultipleColumns")
|
|
{
|
|
// Test with multiple columns
|
|
for ( int i = 3; i < 12; i += 2 )
|
|
{
|
|
INFO(wxString::Format("%i columns", i).c_str());
|
|
pgManager->SetColumnCount(i);
|
|
pgManager->Refresh();
|
|
pgManager->Update();
|
|
wxMilliSleep(500);
|
|
}
|
|
SUCCEED();
|
|
}
|
|
|
|
SECTION("WindowStyles")
|
|
{
|
|
// Recreate grid with all possible (single) flags
|
|
REQUIRE(wxPG_AUTO_SORT == 0x000000010);
|
|
|
|
for ( int i = 4; i < 16; i++ )
|
|
{
|
|
int flag = 1 << i;
|
|
INFO(wxString::Format("Style: 0x%X", flag).c_str());
|
|
ReplaceGrid(pgManager, flag, -1);
|
|
pgManager->Update();
|
|
wxMilliSleep(500);
|
|
}
|
|
SUCCEED();
|
|
|
|
REQUIRE(wxPG_EX_INIT_NOCAT == 0x00001000);
|
|
|
|
for ( int i = 12; i < 27; i++ )
|
|
{
|
|
int flag = 1 << i;
|
|
INFO(wxString::Format("ExStyle: 0x%X", flag).c_str());
|
|
ReplaceGrid(pgManager, -1, flag);
|
|
pgManager->Update();
|
|
wxMilliSleep(500);
|
|
}
|
|
SUCCEED();
|
|
}
|
|
}
|
|
#endif // wxUSE_PROPGRID
|