How to change default Validator Decoration controlsfx - javafx

I use controlsfx in my project, and i tried to find proper way to change default validator decorations, so instead of graphic that it uses CSS decorator as default, but i had no access.
I have no problem to make my own decorator, and decorate some text field, (i define css class, create decorator and it works)
but how can i alter my code that it uses CSS decoration for validation as default!
Example code :
ValidationSupport support = new ValidationSupport();
public void isMax(TextField tf, Boolean b){
Validator<String> validator = (control, value) -> {
boolean condition =
value != null
? !value
.matches(
"[\\x00-\\x20]*[+-]?(((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*" )
: value == null;
return ValidationResult.fromMessageIf(control,"not a number" ,Severity.ERROR , condition);
};
support.registerValidator( tf, b, validator );
}
So what to change so my validation uses CSS styling instead graphic ones.
The code above works, and provides the graphic validation of text field, however the following does not work :
public class MyValid extends StyleClassValidationDecoration {
ValidationSupport support = new ValidationSupport();
public void isMax(TextField tf, Boolean b){
// Decorator.addDecoration(tf,new StyleClassDecoration("warning"));
support.setValidationDecorator(new StyleClassValidationDecoration());
Validator<String> validator = (control, value) -> {
boolean condition =
value != null
? !value
.matches(
"[\\x00-\\x20]*[+-]?(((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*" )
: value == null;
return ValidationResult.fromMessageIf(control,"not a number" ,Severity.ERROR , condition);
};
support.registerValidator( tf, b, validator );
}
The problem is i think either that i dont know to point stylevalidation to coresponding css classes or the problem is in the line that returns ValidationResult.
For example this line of code :
Decorator.addDecoration(tf,new StyleClassDecoration("warning"));
decorates the field, and as a styling resources uses "warning" class in my default .css file.
How can i do this for StyleClassValidationDecoration?

Reworking to show how to use a StyleClassValidtionDecoration.
In ControlsFX if using CSS - you can simply provide the StyleClassValidationDecoration the CSS classes you wish you use.
ValidationSupport validator = new ValidationSupport();
validator.setValidationDecorator(new StyleClassValidationDecoration("myErrorClass", "myWarningClass"));
validator.registerValidator(fieldToValidate, false, this::myValidationForField);

Related

Serilog Custom Sink Formatting Issue with Serilog LogEventPropertyValue

I'm having to create my own custom sink because none of the ones currently available give me what I need.
Issue I have is when fetching the key/value pair Value from the logEvent message in the Emit Method, the value is wrapped with quotation marks & backslashes.
I've tried converting the out value from the dictionary into a string and then removing the unwanted attributes but nothing is working for me.
Method in my Custom Sink Class:
public void Emit(LogEvent logEvent)
{
var properties = logEvent.Properties;
Serilog.Events.LogEventPropertyValue value;
if (properties.TryGetValue("logEventCategory", out value))
{
// Regex.Replace((value.ToString() ?? "").Replace("'", #"\'").Trim(), #"[\r\n]+", " "); // Not working
var notWorking = value.ToString();
var formattedValueNotWorking = value.ToString().Replace("\r\n", "\\r\\n");
}
}
It just seems that any attempted formatting of the key/value pair Value is ignored: You see that the example string value System is wrapped with a \"System\"
All I want is the actual string, not the backslashes or quotation marks that is wrapped around the string.
Creating my own sink is a hard enough task and I just want to keep things simple, have spent two days trying to understand the wider picture in message formatting but with custom sinks it gets too complicated and bloated coding for what I need. All the other standard message structure attributes are rendering OK, such as message / level / timestamp etc, it's just fine tuning the rendering of the propertie values I require in order to save these values into their own columns in my DB.
You need to unwrap the string from the enclosing ScalarValue:
// using Serilog.Events;
public void Emit(LogEvent logEvent)
{
var properties = logEvent.Properties;
Serilog.Events.LogEventPropertyValue value;
if (properties.TryGetValue("logEventCategory", out value) &&
value is ScalarValue sv &&
sv.Value is string rawValue)
{
// `rawValue` is what you're looking for
Looks like I just needed to use the correct syntax for string replace:
public void Emit(LogEvent logEvent)
{
var properties = logEvent.Properties;
Serilog.Events.LogEventPropertyValue value;
if (properties.TryGetValue("logEventCategory", out value))
{
var formattedValueWorking = value.ToString().Replace("\"", "");
var test = formattedValueWorking;
}
}

How to check tag of view in which touch occurred

I am developing a Xamarin.Forms application targeting the iOS platform. I want to only allow stylus input (i.e. disallow finger/direct input) in my entire app except for one single control (a SwitchCell).
For that, I implemented a custom UIApplication class and overrode the SendEvent(UIEvent uievent) method.
In SendEvent I am checking whether the event is a touch event using uievent.Type == UIEventType.Touches. Then I want to detect, if the touch occurred in the SwitchCell in which touch input should be allowed.
Because the SwitchCell is created in my Xamarin.Forms project as XAML, I implemented my own TaggableSwitchCell class inheriting from SwitchCell with a Tag property and registered a CustomRenderer that sets the Tag property of the UITableViewCell on iOS (which works as expected):
public class TaggableSwitchCellRenderer : SwitchCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var cell = base.GetCell(item, reusableCell, tv);
cell.Tag = (item as TaggableSwitchCell).Tag;
Log.Debug("Setting tag to " + cell.Tag);
return cell;
}
}
Then, in the SendEvent method, I check for the tag:
var isTouchAllowed = uievent.AllTouches.Any((touch) =>
{
var uitouch = touch as UITouch;
return uitouch.View != null && uitouch.View.ViewWithTag(Constants.Tag) != null;
});
Running this code on the device (iPad Pro 3rd Generation) works fine for every touch that is not in the SwitchCell. However, if the touch is in the SwitchCell (meaning isTouchAllowed should be true), the following message is printed (the app does not crash):
invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
I know, that the problem is with the uitouch.View.ViewWithTag(Constants.Tag) != null statement, but I don't know how to solve it. I already tried manually checking the view tag using uitouch.View.Tag == Constants.Tag but this leads to the same problem.

SDL Tridion 2011: Dynamically fill or add a metadata field using a C# TBB

Is it possible to set the value of a metadata field dynamically from a TBB? Or is it possible to dynamically add a metadata field that does not necessarily exist on a schema from a TBB?
The reason I want to do this is that I am using DD4T and I want to have the breadcrumb automatically added into the DD4T xml.
I have tried the following:
public override void Transform(Engine engine, Package package)
{
Initialize(engine,package);
var page = GetPage();
string output = page.OrganizationalItem.Title;
var parent = page.OrganizationalItem as StructureGroup;
while (parent != null)
{
output = GetLinkToStructureGroupIndexPage(parent) + Separator + output;
parent = parent.OrganizationalItem as StructureGroup;
}
// I tried this to dynamically add the field
//var metadata = page.Metadata.OwnerDocument.CreateElement("breadcrumb");
//metadata.InnerText = output;
//page.Metadata.AppendChild(metadata);
//I tried this to dynamically set an existing field on the schema
foreach (XmlNode xml in page.Metadata)
{
Log.Debug("Metadata field:" +xml.Name);
if(xml.Name == "breadcrumb")
{
xml.InnerText = output;
}
}
package.PushItem(Package.PageName, package.CreateTridionItem(ContentType.Page, page));
}
However, neither of these methods seem to work. Is this impossible?
DD4T has utility class FieldsBuilder with AddFields method where you can inject additional metadata. DD4T has a TBB which does update component metadata from Folder Metadata and it is called InheritMetadataComponent.
You could take a look at this here and you could implement the same:
http://code.google.com/p/dynamic-delivery-4-tridion/source/browse/trunk/dotnet/DD4T.Templates/InheritMetadataComponent.cs
FieldsBuilder.AddFields(component.MetadataFields, tcmFields, 1, false, mergeAction, Manager);
The easiest approach is to create a template class which implements DD4T.Templates.Base.BasePageTemplate. In that class, you implement the method TransformPage, which takes a DD4T page as its argument. You can access the 'TCM page' using the method GetTcmPage().
Example:
using TCM = Tridion.ContentManager.CommunicationManagement;
using Dynamic = DD4T.ContentModel;
public class MyTemplate : BasePageTemplate
{
protected override void TransformPage(Dynamic.Page page)
{
TCM.Page tcmPage = GetTcmPage();
string breadCrumbs = GetBreadCrumbs (tcmPage); // TODO: implement GetBreadCrumbs
Field f = new Field();
f.Name = "breadCrumbs";
f.FieldType = FieldType.Text;
f.Values.Add(breadCrumbs);
page.MetadataFields.Add("breadCrumbs", f);
}
}
page.MetadataFields.Add(name, field); should work if your template extends the DD4T.Templates.Base.BasePageTemplate
You can also take a look at the source of the Add inherited metadata to page TBB in DD4T, that also shows a way of adding Metadata which gets published to the broker.

Use DisplayNameAttribute in ASP.NET

I want to bind a List to a GridView on a web page, but override the way the property names display via annotation. I thought System.ComponentModel would work, but this doesn't seem to work. Is this only meant for Windows Forms?:
using System.ComponentModel;
namespace MyWebApp
{
public class MyCustomClass
{
[DisplayName("My Column")]
public string MyFirstProperty
{
get { return "value"; }
}
public MyCustomClass() {}
}
Then on the page:
protected void Page_Load(object sender, EventArgs e)
{
IList<MyCustomClass> myCustomClasses = new List<MyCustomClass>
{
new MyCustomClass(),
new MyCustomClass()
};
TestGrid.DataSource = myCustomClasses;
TestGrid.DataBind();
}
This renders with "MyFirstProperty" as the column header rather than "My Column." Isn't this supposed to work?
When using .net 4 or later you can use gridview1.enabledynamicdata(typeof(mytype)). I haven't looked at all the types you can use there but I know the [displayname("somename")] works well but the [browsable(false)] doesn't omit the column from the grid. It looks like a knit one slip one from MS. at least you can easily rename column names and to omit a column I just declare a variable instead of using a property. It has the same effect...
Just by the way, using the designer to create columns is the easy way out but to just show a different column name takes way to much time especially with classes with many fields.
What SirDemon said...
The answer appears to be no, you can't. At least not out of the box.
The System.Web.UI.WebControls.GridView uses reflected property's name:
protected virtual AutoGeneratedField CreateAutoGeneratedColumn(AutoGeneratedFieldProperties fieldProperties)
{
AutoGeneratedField field = new AutoGeneratedField(fieldProperties.DataField);
string name = fieldProperties.Name; //the name comes from a PropertyDescriptor
((IStateManager) field).TrackViewState();
field.HeaderText = name; //<- here's reflected property name
field.SortExpression = name;
field.ReadOnly = fieldProperties.IsReadOnly;
field.DataType = fieldProperties.Type;
return field;
}
While System.Windows.Forms.DataGridView uses DisplayName if available:
public DataGridViewColumn[] GetCollectionOfBoundDataGridViewColumns()
{
...
ArrayList list = new ArrayList();
//props is a collection of PropertyDescriptors
for (int i = 0; i < this.props.Count; i++)
{
if (...)
{
DataGridViewColumn dataGridViewColumnFromType = GetDataGridViewColumnFromType(this.props[i].PropertyType);
...
dataGridViewColumnFromType.Name = this.props[i].Name;
dataGridViewColumnFromType.HeaderText = !string.IsNullOrEmpty(this.props[i].DisplayName) ? this.props[i].DisplayName : this.props[i].Name;
}
}
DataGridViewColumn[] array = new DataGridViewColumn[list.Count];
list.CopyTo(array);
return array;
}
Unfortunately, while you can override the CreateAutoGeneratedColumn, neither the missing DisplayName nor underlying property descriptor gets passed, and you can't override CreateAutoGeneratedColumns (although you could CreateColumns).
This means you'd have to iterate over reflected properties yourself and in some other place.
If all you care about is the header text in GridView, just use the HeaderText property of each field you bind. If you're autogenerating the columns, you just set the HeaderText after you've bound the GridView.
If you want a GridView that takes into account some attribute you placed on the properties of your bound class, I believe you'll need to create your own GridView.
I may be wrong, but I've not seen any ASP.NET Grid from control vendors (at least Telerik , Janus Systems and Infragistics) do that. If you do it, maybe sell the idea to them.
Are you using .net4, what you need to do is to set enabledynamicdata on the grid view to true.
You can do it now on asp.net mvc2. It works just like that

Accessing the object/row being edited in Dynamic Data

I'm modifying the "Edit.aspx" default page template used by ASP.NET Dynamic Data and adding some additional controls. I know that I can find the type of object being edited by looking at DetailsDataSource.GetTable().EntityType, but how can I see the actual object itself? Also, can I change the properties of the object and tell the data context to submit those changes?
Maybe you have found a solution already, however I'd like to share my expresience on this.
It turned out to be a great pita, but I've managed to obtain the editing row. I had to extract the DetailsDataSource WhereParameters and then create a query in runtime.
The code below works for tables with a single primary key. If you have compound keys, I guess, it will require modifications:
Parameter param = null;
foreach(object item in (DetailsDataSource.WhereParameters[0] as DynamicQueryStringParameter).GetWhereParameters(DetailsDataSource)) {
param = (Parameter)item;
break;
}
IQueryable query = DetailsDataSource.GetTable().GetQuery();
ParameterExpression lambdaArgument = Expression.Parameter(query.ElementType, "");
object paramValue = Convert.ChangeType(param.DefaultValue, param.Type);
Expression compareExpr = Expression.Equal(
Expression.Property(lambdaArgument, param.Name),
Expression.Constant(paramValue)
);
Expression lambda = Expression.Lambda(compareExpr, lambdaArgument);
Expression filteredQuery = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, query.Expression, lambda);
var WANTED = query.Provider.CreateQuery(filteredQuery).Cast<object>().FirstOrDefault<object>();
If it's a DD object you may be able to use FieldTemplateUserControl.FindFieldTemplate(controlId). Then if you need to you can cast it as an ITextControl to manipulate data.
Otherwise, try using this extension method to find the child control:
public static T FindControl<T>(this Control startingControl, string id) where T : Control
{
T found = startingControl.FindControl(id) as T;
if (found == null)
{
found = FindChildControl<T>(startingControl, id);
}
return found;
}
I found another solution, the other ones did not work.
In my case, I've copied Edit.aspx in /CustomPages/Devices/
Where Devices is the name of the table for which I want this custom behaviour.
Add this in Edit.aspx -> Page_Init()
DetailsDataSource.Selected += entityDataSource_Selected;
Add this in Edit.aspx :
protected void entityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
Device device = e.Results.Cast<Device>().First();
// you have the object/row being edited !
}
Just change Device to your own table name.

Resources