IntelliJ copy class field names and paste them into method as arguments? - intellij-idea

I am designing a Vaadin UI component with around 30 components
e.g.
public class MyView {
private TextField foo;
private TextField bar;
private TextField bobby;
private TextField x;
private TextField y;
private TextField z;
private TextField ad;
private TextField nauseum;
private TextField thisisboring;
public MyView() {
formview.add(foo,bar,bobby,tables,x,y,z,ad,nauseum,thisisboring);
}
}
I want to add all these fields as arguments into the formview.add() method. At the moment I am manually adding each field to this method.
Is there an easier way for IntelliJ to generate all these field names as arguments of a function?
(I really don't want to type 30 fields into a method)

Not a perfect solution, but use multi-caret selection:
First double click on the first identifier you need, then double click on each following identifier while holding Alt+Shift down. You should have all the identifiers you need selected. Copy them to the clipboard using Cmd/Ctrl+C. Put the caret between the parentheses of formview.add(). Don't hold any keys down, so you have only a single caret left. Paste Cmd/Ctrl+V. All identifiers will be pasted on separate lines. Hold Alt and click and drag the mouse past the end of the selected lines (except the last one). This should add a caret at the end of every line. Type a , to add a comma between the pasted identifiers and optionally join lines Ctrl+Shift+J to put the call on a single line.
This should be quite a bit less work than typing everything out.

I can think of one naive approach: Declaring it like
private AbstractField<String> foo, bar, bobby, x, y, z, ad, nauseum, thisisboring;
and just copy/paste (or if there are multiple field types, at least group the same types)?
Or maybe better approach: as the root of the problem is probably too many parameters, we can encapsulate it:
private FormFields formFields;
public MyView() {
formview.add(formFields.asArray());
}
public static class FormFields {
private TextField foo;
...
public Component[] asArray() {
return new Component[]{foo, bar, bobby, x, y, z, ad, nauseum, thisisboring};
}
... //getters etc.
}

Related

Enums and selection lists in XAML

I've been at this all day and could now use some help. Thank you in advance.
Enums cannot be declared as partial; classes can. I had the need to combine multiple enum lists (which have assigned integers that are unique across enum groups) in a single list that is selectable in XAML using an attached property. I have looked a numerous things and I am still lost.
First, let's say I have the following code:
public enum Items {One, Two, Three};
public class DepObj : DependencyObject
{
public static readonly DependencyProperty
Field = DependencyProperty.RegisterAttached("Field", typeof(Items), typeof(DepObj), new PropertyMetadata(Items.One, OnFieldChanged));
public static Items GetField(DependencyObject d)
{
return (Items)d.GetValue(Field);
}
public static void SetField(DependencyObject d, Items field)
{
d.SetValue(Field, field);
}
private static void OnFieldChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SetField(d, (Items)e.NewValue);
}
}
Now, in XAML, I can set an Items property to "One" for instance. In XAML, I get a droplist of items that may be selected (One, Two, Three). Is there something special built into the XAML editor for enums that knows how to display this list? Or, is there something I can specify on any class that XAML would call within the class to provide this selection list?
I have looked at System.Enum (Microsoft System.Enum) and what it inherits from and I don't see what I need to do to provide equivalent functionality for my own class (or even a struct, if value types are required).
So my question is twofold:
How does XAML provide selection lists for enums
Is this functionality available to embed/use in classes that XAML will recognize
Thank you in advance.

Changing states when entities intersect

I am making a maze that the player has to navigate with the mouse, but they lose when the hit a wall. I want to make sure the player has the mouse in the right place to start, so I am trying to switch to the game state once the mouse intersects with a square indicator on screen.
In the tutorial I was learning from, they did this:
public static class Point extends AbstractEntity {
public Point(double x, double y, double width, double height) {
super(x, y, width, height);
}
#Override
public void draw() {
glBegin(GL_POINTS);
glVertex2d(x, y);
}
#Override
public void update(int delta) {
// Blank
}
}
Point.setLocation(Mouse.getX(), 480 - Mouse.getY() - 1);
if(Maze1.intersects(Point)){
System.out.println("You would have lost");
}
I tried to do this:
case MAZE:
if(Maze1.intersects (Point) ){
state = State.GAMEOVER;
}
break;
I get the error, "Point cannot be resolved to a variable". Please help.
It looks like when you call Maze1.intersects you are passing the actual Point class rather than an instance of that class. This is why you get the "Point cannot be resolved to a variable" error. You need to create an instance of Point, call setLocation on that instance and then pass that into Maze1.intersects.
For your example to work I would either remove the argument on Maze1.intersects and have it access the Point class directly or change Point to it's no longer static, declare an instance of Point and pass that instance into Maze1.intersect.
Declaring the Point class as static does not mean you can pass the class into method, etc, like a regular variable as it's simply a way of sharing data and behaviour. Also, keep in mind that by declaring Point as static you are saying that there will only ever be one Point.
I would maybe consider dropping the static keyword and creating an instance of Point classed "startingPoint". You can then pass this into Maze1.intersects. Then if you need to determine if the player intersects with other "points" in the maze, then you can create other instances to represent those points.

Listbox.SelectedItems.Add not causing SelectionChanged event

I have a custom user control extending the Listbox class. Inside of it I am overriding OnSelectionChanged to add/remove Adorners to any selected/unselected items. This all works when I select an item using the mouse, but when I programmatically add items to the listbox using
myListBox.SelectedItems.Add(newItem) // newItem is already a member of myListBox.Items
It does not execute the OnSelectionChanged code.
Update: Unless I'm crazy (which is always possible) it seems there is a difference in behaviour between calling this from the parent object
myListBox.SelectedItems.Add(newItem)
and this method inside my extended listbox class
Public Sub AddSelectedItem(newItem as Object)
Me.SelectedItems.Add(newItem)
End Sub
For some reason the second option is triggering the event while the first one isn't.
you need to add this line of code first
myListBox.Items.Add(newItem)
The solution here is that calling SelectedItems.Add() from inside an extension of ListBox
public class MyListBox : ListBox
{
public void AddSelectedItems(object newSelectedItem)
{
// works
this.SelectedItems.Add(newSelectedItem);
}
}
will trigger the OnSelectionChanged event.
Calling it like this from the window will not trigger the event
private sub SomeWindowMethod()
{
// does not work
this.MyListBoxInstance.SelectedItems.Add(newSelectedItem);
}

Overload DataGridViewCellStyle and give a default value

I'm writing a custom DataGridView object for a large project to hand out to a bunch of developers to make our app sections look consistent.
I want to set defaults for many of the properties of the DataGridView, and I can set many of them like this:
<System.ComponentModel.Browsable(True), System.ComponentModel.DefaultValue(DataGridViewAutoSizeColumnsMode.Fill)>_
Public Overloads Property AutoSizeColumnsMode() As DataGridViewAutoSizeColumnMode
Get
Return MyBase.AutoSizeColumnsMode
End Get
Set(ByVal value As DataGridViewAutoSizeColumnMode)
MyBase.AutoSizeColumnsMode = value
End Set
End Property
These properties overload with their defaults just fine. Its when I started trying to make default Cell styles that I ran into the issue. Since the DataGridViewCellStyle is a class, I cannot make a constant out of it. I've tried changing all of the settings to what I want them to be in the class constructor, and that works great, except that changes made in the designer properties just get set back as soon as the app runs. So putting the changes in the constructor won't do.
Is there anywhere else I can put code that only runs when the control is first dropped on the designer? or any other way of setting a default?
I ran into this problem too. My solution works around the requirement for the DefaultValue argument to be a compile-time constant. I thought, wouldn't it be sufficient to set the value in the class constructor (defined by the static constructor in C#, and the shared constructor in VB) instead?
This seems to be an good work-around in my case, though there are probably instances where it might break since it's not actually present in the meta-data until the class constructor is called upon loading the class, but for a Designer attribute that should be acceptable. Because DefaultValueAttribute.SetValue is protected, I had to define a derived class that makes it public.
This works fine in the designer, it recognizes when the value is the same as the default and omits it from the generated code when possible, and only generates the differences from the default.
Here's the code in C#, this should work in VB too but I'm not overly familiar with its syntax so I'll have to leave that up to you.
public partial class HighlightGrid : DataGridView
{
// Class constructor
static MethodGrid()
{
// Get HighlightStyle attribute handle
DefaultValueSettableAttribute attr =
TypeDescriptor.GetProperties(typeof(HighlightGrid))["HighlightStyle"]
.Attributes[typeof(DefaultValueSettableAttribute)]
as DefaultValueSettableAttribute;
// Set default highlight style
DataGridViewCellStyle style = new DataGridViewCellStyle();
style.BackColor = Color.Chartreuse;
attr.SetValue(style);
}
[DefaultValueSettable, Description("Cell style of highlighted cells")]
public DataGridViewCellStyle HighlightStyle
{
get { return this.highlightStyle; }
set { this.highlightStyle = value; }
}
// ...
}
// Normally the value of DefaultValueAttribute can't be changed and has
// to be a compile-time constant. This derived class allows setting the
// value in the class constructor for example.
public class DefaultValueSettableAttribute : DefaultValueAttribute
{
public DefaultValueSettableAttribute() : base(new object()) { }
public new void SetValue(Object value) { base.SetValue(value); }
}
Actually, I thought about it a while longer and came across a simpler solution for my issue. This does not work for all cases because it relies on the fact that the person using the custom component will likely never want to revert an entire CellStyle back to windows defaults. I ended up comparing a new CellStyle to the current one in the constructor, and only setting the style if they matched. This way it won't overwrite changes, but it will set it up the first time.
Public Class CustomDataGridView
Inherits System.Windows.Forms.DataGridView
Private RowStyle As New DataGridViewCellStyle
Public Sub New()
RowStyle.BackColor = Color.FromArgb(223, 220, 200)
RowStyle.Font = New Font("Arial", 12.75, FontStyle.Bold, GraphicsUnit.Point)
RowStyle.ForeColor = Color.Black
RowStyle.SelectionBackColor = Color.FromArgb(94, 136, 161)
If MyBase.RowsDefaultCellStyle.ToString = (New DataGridViewCellStyle).ToString Then
MyBase.RowsDefaultCellStyle = RowStyle
End If
End Sub
End Class
Just goes to show, Just because you have a golden hammer, doesn't mean that every problem is a nail.

BindingSource / BindingNavigator: How to prevent editing of bound DataSource?

I created a Data Source with VB.NET and Visual Studio 2005. I dragged the data source onto my dialog, and VS created the text boxes with the members of my linked Object, a System.Windows.Forms.BindingSource and a System.Windows.Forms.BindingNavigator.
I populate the List (called myList), set myList as the DataSource in the BindingSource, and things work peachy except for the fact that I want this to be read-only. If the user changes something in one of the text boxes, it saves the changes.
I tried creating a read-only collection to bind to the BindingSource, but that didn't solve the problem:
Dim detailsDlg As New dlgMyDetails
Dim readOnlyList As New ReadOnlyCollection(Of MyObjects)(myList)
detailsDlg.MyBindingSource.DataSource = readOnlyList
detailsDlg.ShowDialog()
I guess I could disable all of the text boxes, but that seems a bit heavy-handed, plus I'd probably want to change the font color so that it's easier to read.
Ideally, I probably wouldn't care if users were able to set focus to the text boxes, or even edit the contents, but I just wouldn't want any changes to persist. That is, if someone edited something, used the navigator to go to the next record, and then returned, I'd want it as it was before the user played with it.
Any suggestions / guidance?
Thanks in advance!
From a Model-View-Control perspective, the constraint you want is not on the model or control, but the view. The view should restrict what is editable on the screen.
If it truly is read-only, why not go with a read-only user interface element, ie, a label? The reason you do this is to reduce confusion to the user. If it is a textbox, there is a reasonable expectation that at some point the data becomes editable. If this is not the case, then presenting a disabled textbox is likely not the right UI element to present, rather, as mentioned, a label.
Instead of making a ReadOnlyCollection you can change the property in your class (MyObjects) to ReadOnly or add attribute System.ComponentModel.ReadOnly(true) to your property, example:
class Person
{
public Person(int id, string name, string address)
{
_id = id;
Name = name;
Address = address;
}
private int _id = 0;
public int ID { get { return _id; } }
[System.ComponentModel.ReadOnly(true)]
public string Name { get; set; }
public string Address { get; set; }
}
ID and Name is going to be readonly, sorry if the example is in C#. Hope this helps.
Cheers.