bool ObjectsPropgridHelper::OnPropertyChanged(gd::Object * object, gd::Layout * layout, wxPropertyGridEvent& event) { if ( !grid || !object ) return false; auto readEnumPropertyString = [&event](std::map<gd::String, gd::PropertyDescriptor> properties) { const std::vector<gd::String> & choices = properties[event.GetProperty()->GetLabel()].GetExtraInfo(); unsigned int id = event.GetPropertyValue().GetLong(); if (id < choices.size()) { return gd::String(choices[id]); } return gd::String(""); }; if ( event.GetPropertyName().substr(0,10) == "AUTO_PROP:" ) { gd::String autoName = event.GetPropertyName().substr(10); if ( !object->HasBehaviorNamed(autoName)) { event.Veto(); return false; } gd::Behavior & behavior = object->GetBehavior(autoName); gd::String value = event.GetPropertyValue().GetString(); //Special case for enums. if (wxEnumProperty * enumProperty = dynamic_cast<wxEnumProperty*>(event.GetProperty())) value = readEnumPropertyString(behavior.GetProperties(project)); if (!behavior.UpdateProperty(event.GetProperty()->GetLabel(), value, project)) { event.Veto(); return false; } } else if ( event.GetPropertyName().substr(0,8) == "OBJ_PROP" ) { gd::String value = event.GetPropertyValue().GetString(); //Special case for enums. if (wxEnumProperty * enumProperty = dynamic_cast<wxEnumProperty*>(event.GetProperty())) value = readEnumPropertyString(object->GetProperties(project)); if (!object->UpdateProperty(event.GetProperty()->GetLabel(), value, project)) { event.Veto(); return false; } } return false; }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ void PropertiesView::onPropertyGridChanging(wxPropertyGridEvent& _event) { wxPGProperty* const pWXProperty = _event.GetProperty(); // TODO Don't assume this is a string. std::string newValue = wx2std(_event.GetValue().GetString()); if (pWXProperty->GetClientData() != NULL) { I_Property* pProperty = static_cast<I_Property*>(pWXProperty->GetClientData()); assert(pProperty != NULL); if (!pProperty->getPublisher().getController().canChangeProperty(*pProperty, newValue)) { // Veto the event. _event.Veto(); // Set the validation failure behavior. _event.SetValidationFailureBehavior(wxPG_VFB_STAY_IN_PROPERTY //| wxPG_VFB_BEEP //| wxPG_VFB_SHOW_MESSAGE ); } } }
void ChannelInspectorT::OnPropertyGridChanging(wxPropertyGridEvent& Event) { if (m_ModelDoc==NULL) return; const ArrayT<unsigned int>& Selection=m_ModelDoc->GetSelection(CHAN); if (Selection.Size()!=1) return; // Changing a property by pressing ENTER doesn't change the selection. In consequence the property refresh below does not result in // any change since selected properties are not updated (because the user could be in the process of editing a value). // Since the user is definitely finished editing this property we can safely clear the selection. // ClearSelection(); const unsigned int ChanNr =Selection[0]; const wxString PropName=Event.GetPropertyName(); m_IsRecursiveSelfNotify=true; bool ok=true; if (PropName=="Name") { ok=m_Parent->SubmitCommand(new CommandRenameT(m_ModelDoc, CHAN, ChanNr, Event.GetValue().GetString())); } else if (PropName.StartsWith("Joints.")) { ok=m_Parent->SubmitCommand(new CommandUpdateChannelT(m_ModelDoc, ChanNr, Event.GetProperty()->GetIndexInParent(), Event.GetValue().GetBool())); } else { // Changing child properties (e.g. "Pos.x" to "5") also generates events for the composite parent (e.g. "Pos" to "(5, 0, 0)")! // That is, if the following line is uncommented, it produces false warnings as well: // wxMessageBox("Unknown property label \""+Name+"\".", "Warning", wxOK | wxICON_ERROR); } wxASSERT(Event.CanVeto()); // EVT_PG_CHANGING events can be vetoed (as opposed to EVT_PG_CHANGED events). if (!ok) Event.Veto(); m_IsRecursiveSelfNotify=false; }
bool ObjectsPropgridHelper::OnPropertySelected(gd::Object * object, gd::Layout * layout, wxPropertyGridEvent& event) { if ( !grid || !object ) return false; //Check if the object is global bool globalObject = false; for (std::size_t i = 0;i<project.GetObjectsCount();++i) { if ( &project.GetObject(i) == object ) { globalObject = true; break; } } if ( event.GetColumn() == 1) //Manage button-like properties { if ( event.GetPropertyName() == _("Edit") ) { object->EditObject(grid, project, mainFrameWrapper); for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j) project.GetUsedPlatforms()[j]->GetChangesNotifier().OnObjectEdited(project, globalObject ? NULL : layout, *object); //Reload resources : Do not forget to switch the working directory. wxString oldWorkingDir = wxGetCwd(); if ( wxDirExists(wxFileName::FileName(project.GetProjectFile()).GetPath())) wxSetWorkingDirectory(wxFileName::FileName(project.GetProjectFile()).GetPath()); if (layout) object->LoadResources(project, *layout); wxSetWorkingDirectory(oldWorkingDir); } else if ( event.GetPropertyName() == _("Help")) { auto metadata = gd::MetadataProvider::GetObjectMetadata(project.GetCurrentPlatform(), object->GetType()); gd::HelpFileAccess::Get()->OpenPage(metadata.GetHelpUrl()); } else if ( event.GetPropertyName() == _("Variables") ) { gd::ChooseVariableDialog dialog(grid, object->GetVariables(), true); dialog.SetAssociatedObject(&project, layout, object); if ( dialog.ShowModal() == 1 ) { for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j) project.GetUsedPlatforms()[j]->GetChangesNotifier().OnObjectVariablesChanged(project, globalObject ? NULL : layout, *object); //Update the grid: if ( grid->GetProperty("OBJECT_VARIABLES_CATEGORY") != NULL) grid->SetPropertyLabel("OBJECT_VARIABLES_CATEGORY", _("Object variables") + " (" + gd::String::From(object->GetVariables().Count()) + ")"); } } else if ( event.GetPropertyName() == "AUTO_ADD" ) { return gd::ChooseBehaviorTypeDialog::ChooseAndAddBehaviorToObject(grid, project, object, layout, globalObject); } else if ( event.GetPropertyName() == "AUTO_REMOVE" ) { //Create behavior array wxArrayString behaviorsStr; //Fill array std::vector <gd::String> behaviors = object->GetAllBehaviorNames(); for (std::size_t i = 0;i<behaviors.size();++i) behaviorsStr.Add(object->GetBehavior(behaviors[i]).GetName()); int selection = wxGetSingleChoiceIndex(_("Choose the behavior to delete"), _("Choose the behavior to delete"), behaviorsStr); if ( selection == -1 ) return false; object->RemoveBehavior(behaviors[selection]); UpdateBehaviorsSharedData(project, globalObject ? NULL : layout); for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j) project.GetUsedPlatforms()[j]->GetChangesNotifier().OnBehaviorDeleted(project, globalObject ? NULL : layout, *object, behaviors[selection]); return true; } else if ( event.GetPropertyName().substr(0,12) == "AUTO_RENAME:" ) { event.Veto(); gd::String oldName = event.GetPropertyName().substr(12); if ( !object->HasBehaviorNamed(oldName)) return true; gd::Behavior & behavior = object->GetBehavior(oldName); gd::String newName = wxGetTextFromUser(_("Enter a new name for the behavior"), _("Rename a behavior"), behavior.GetName()); if ( newName == behavior.GetName() || object->HasBehaviorNamed(newName) || newName.empty() ) return false; object->RenameBehavior(oldName, newName); UpdateBehaviorsSharedData(project, globalObject ? NULL : layout); for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j) project.GetUsedPlatforms()[j]->GetChangesNotifier().OnBehaviorRenamed(project, globalObject ? NULL : layout, *object, behavior, oldName); return true; } else if ( event.GetPropertyName().substr(0,5) == "AUTO:" ) { event.Veto(); gd::String autoName = event.GetPropertyName().substr(5); if ( !object->HasBehaviorNamed(autoName)) return true; gd::Behavior & behavior = object->GetBehavior(autoName); behavior.EditBehavior(grid, project, layout, mainFrameWrapper); //EditBehavior always need a valid layout! for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j) project.GetUsedPlatforms()[j]->GetChangesNotifier().OnBehaviorEdited(project, globalObject ? NULL : layout, *object, behavior); } } return false; }
void PropertyPane::OnPropertyChanging(wxPropertyGridEvent &event) { wxPGProperty *prop = event.GetProperty(); wxVariant value = event.GetValue(); wxString sqlQuery, sqlUpdate, type, format, minStr, maxStr; long min, max, requestedValue; // event.GetValue() is always numeric base wxVariant. // Use wxPGProperty::ValueToString(wxVariant& value, int argFlags = 0) to // retrieve the string based property value for any kind of wxYYYProperty. if (prop && _propDB) { wxLogVerbose(wxT("OnPropertyChanging %s"), prop->ValueToString(value)); sqlQuery << wxT("SELECT PropertyType, PropertyFormat FROM PropTbl WHERE DisplayedName = '") << prop->GetLabel() << wxT("'"); wxSQLite3ResultSet set = _propDB->ExecuteQuery(sqlQuery); if (set.NextRow()) { type = set.GetAsString(wxT("PropertyType")); format = set.GetAsString(wxT("PropertyFormat")); } set.Finalize(); /* property format checker */ if (type == wxT("Numeric")) { wxStringTokenizer tokenizer(format, wxT(";")); minStr = tokenizer.GetNextToken(); maxStr = tokenizer.GetNextToken(); if (minStr.ToLong(&min) && maxStr.ToLong(&max)) { requestedValue = value.GetLong(); if ((requestedValue < min) || (requestedValue > max)) { event.Veto(); wxLogError(_("Input number out of range! Max = %s, Min = %s"), maxStr, minStr); return; } } } else if (type == wxT("List")) { /* no check item now. */ } else if (type == wxT("String")) { // TODO: check for max length } /* update database record */ _pgUpdatedFromUI = true; sqlUpdate << wxT("UPDATE PropTbl SET CurrentValue = '") << prop->ValueToString(value) << wxT("' WHERE DisplayedName = '") << prop->GetLabel() << wxT("'"); if (_propDB->ExecuteUpdate(sqlUpdate) != 1) { wxLogError(_("Failed to update property %s"), prop->GetLabel()); event.Veto(); } } }