I am using the Piccolo 2D ZUI library in a C# Winform application.
One of the examples that the library shows is adding a squiggle (line drawing) handler to the canvas.
The problem is that if you enable the squiggle handler and allow canvas dragging then both events occur at the same time.
What I would like to do is inherit the PDragEventhandler so that it only runs when the CTRL is not pressed down. Then when the CTRL key is pressed down the squiggler will run (I got this figured out).
The code used for the drag handler is:
InitializeComponent();
//add input event listener
pCanvas1.AddInputEventListener(new PDragEventHandler());
Can I inherit the PDragEventhandler and then say only run when CTRL not pressed? Or do I need to recompile the Piccolo library to enable this feature?
For java it is extremely straight foward. In the initialize you will want to make the following changes:
public void mouseDragged(PInputEvent e) {
super.mouseDragged(e);
// Update the squiggle while dragging.
updateSquiggle(e);
}
to
public void mouseDragged(PInputEvent e) {
super.mouseDragged(e);
if (e.isControlDown()) {
updateSquiggle(e);
}
}
Explanantion: This is possible because PInputEvent inherits the java event and therefore has the isControlDown() option. In C# this is not the case and you will need to extend it manually, or add it. There is a description of how to do it for C# (which I am not very familiar with) in Part 3 of the following tutorial.
For C# I would assume the listener should look something like the following:
protected void squiggle_ControlDown(object sender, PInputEventArgs e) {
PNode node = (PNode)sender;
switch (e.KeyCode) {
case Keys.Control:
updateSquiggle();
break;
}
}
I hope this helps, I wish it hadn't been so long since I'd used C# or I could have given you a more specific answer.
You can override acceptsEvent() method to control events dispatch. For example to accept events only with control key modifier:
public class DragHandler extends PDragEventhandler {
#Override
public boolean acceptsEvent(PInputEvent event, int type) {
return super.acceptsEvent(event, type) && event.isControlDown();
}
}
Related
I'm practicing with buttons in Unity and I'm trying to figure out how I can assign different methods to a button without using the OnClick thing in the inspector so I came up with this.
public class UIButtons : MonoBehaviour
{
void Start()
{
var buttons = FindObjectsOfType<Button>(); //I should probably have this outside of this method
foreach (Button button in buttons)
{
button.onClick.AddListener(() => ButtonPressed(button));
}
}
void ButtonPressed(Button button)
{
switch (button.name)
{
case "MMPlayButton": //The main menu play button
Debug.Log("Play button pressed");
break;
case "PlayButton":
Debug.Log("Play button pressed");
break;
case "SettingsButton":
Debug.Log("Settings button pressed");
break;
case "QuitButton":
Debug.Log("Quit button pressed");
break;
default:
Debug.LogWarning("Button doesn't have a case: " + button.name);
//could do some kind of pop up message saying the button pressed isn't available or something
break;
}
}
}
I know this can work, however, I'd imagine this is a horrible way to do things because it's using the name so if I were to change the name or make a typo it breaks, or an issue I did encounter was if buttons have the same name, and if I add more buttons I'd have to add more cases and then it would probably turn out to be a giant mess.
I could be wrong though and maybe this is an alright idea, but I doubt it so looking for some help with this.
You can simplify this by using inheritance. Create a base class for all of your buttons to use, ie. UIButtonBase that has the OnButtonPressed virtual method. Then create specific buttons that inherit this base class and override the OnButtonPressed method.
Base Class
public class UIButtonBase: MonoBehaviour
{
protected virtual void Awake()
{
var button = GetComponent<Button>();
if (button)
{
button.onClick.AddListener(() => OnButtonPressed());
}
else
{
Debug.Log(name + " does not have a Button component!");
}
}
protected virtual void OnButtonPressed()
{
Debug.Log("UIButtonBase::OnButtonPressed()");
}
}
Specific implementation of a button
public class SettingsButton : UIButtonBase
{
protected override void OnButtonPressed()
{
Debug.Log("SettingsButton::OnButtonPressed()");
// If you want the base functionality as well, add..
//
base.OnButtonPressed();
}
}
For setup, create a button and add this script to it. You may need to change the GetComponent in Awake (UIButtonBase) to GetComponentInParent or GetComponentInChildren, depending on your gameobjects hierarchy. You could also expose the Button component in the UIButtonBase script and use that reference.
I know this won't be a good answer but if I were you, I would make different files for different buttons. Like SettingButton.cs, PlayButton.cs etc.
This approach will not add a huge amount of burden to your code but as the functionalities of your buttons increase, this approach will greatly help to keep your code organized.
We are internationalizing a mobile app my team is developing, and I noticed the "Cancel" button in the SearchBar is not translating (everything else is translating just fine) - it always says "Cancel" in English no matter what language I change the iPad simulator to. If I can set the text myself, then I can ensure it's internationalized properly. So...
How do I change the "Cancel" button text on a Xamarin.Forms SearchBar? I've tried a custom renderer, but am having difficulty targeting the Cancel button subview. This answer seems to do a great job of explaining how to do that in Objective C, but I'm having trouble translating it into C# within the Xamarin.Forms framework.
Create a new custom renderer for iOS. Something like CustomSearchBarRenderer and subclass the Xamarin's original SearchBarRenderer
public class CustomSearchBarRenderer : SearchBarRenderer { }
I'd probably try to override OnElementChanged method and set the custom title after the base class has done all the work. Like this:
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
var cancelButton = Control.FindDescendantView<UIButton>();
cancelButton.Title = "Whatever";
}
Edit: Please be aware that the cancelButton might get recreated at some point so you might have to set the title at some other point too. However, this should be a good starting point.
You can also take a look at the current SearchBarRenderer implementation here.
I combined the answers and set the button text on each event which is needed. I also fixed the showing and hiding of the cancel button (see here):
using FestivalHolledauApp.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.Linq;
[assembly: ExportRenderer(typeof(SearchBar), typeof(CustomSearchBarRenderer))]
namespace FestivalHolledauApp.iOS
{
public class CustomSearchBarRenderer : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
// Fixing Cancel button
if (e.NewElement != null)
{
this.Control.TextChanged += (s, ea) =>
{
this.Control.ShowsCancelButton = true;
SetCancelButtonText();
};
this.Control.OnEditingStarted += (s, ea) => //when control receives focus
{
this.Control.ShowsCancelButton = true;
SetCancelButtonText();
};
this.Control.OnEditingStopped += (s, ea) => //when control looses focus
{
this.Control.ShowsCancelButton = false;
};
}
}
private void SetCancelButtonText()
{
var cancelButton = Control.Descendants().OfType<UIButton>().FirstOrDefault();
if (cancelButton != null)
{
cancelButton.SetTitle("Schließen", UIControlState.Normal);
}
}
}
}
I've come over the same issue with ...
the "Cancel" button in a UISearchBar
the "Back" button to prior pages without title
context menu actions like "Cut", "Copy" and "Paste"
the "Done" buttons on date pickers and multiline editors
Everything else I got localized with resource based localization.
There are a lot of hacks out there finding the native buttons and setting texts manually but I knew this was not the way it was meant to be. So I digged deeper and found the following excellent article from Gerald Versluis:
https://blog.verslu.is/xamarin/xamarin-forms-xamarin/localization-default-ios-controls/
For me, this just meant to add the following block to my Info.plist:
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>de</string>
</array>
With this, iOS automatically translated all the UI elements for the current system culture (without adding these text to any resource files).
The following code is giving me a small issue.
public void ButtonShort()
{
lcd.WriteLine(" K ");
GpioPinValue Readbutton = ButtonS.Read();
if (buttonS == GpioPinValue.Low)
{
Temp = Temp + "K";
}
}
Temp is a list which is empty by default. So every button press should add ONE 'K'.
But it actually registers 'K' multiple times.
What I want is that one button press only registers one 'K'.
Thanks for the help!
I can't directly help you for C#, but had a similar problem once where I used Java with the Pi4J Lib for the GPIO Access.
In there, you have events which are triggered by a changing input pin value. I catched that event and checked in the routine wether the state was high/low, depending on what had to be the actual trigger for counting.
Code in Java was quite straigt forward:
public void handleGpioPinInputStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
if (event.getState() == PinState.HIGH) {
[...]
}
}
[Edit - got interested... :-)]
Perhaps the following code from here will help:
private void buttonPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
// toggle the state of the LED every time the button is pressed
if (e.Edge == GpioPinEdge.FallingEdge)
{
ledPinValue = (ledPinValue == GpioPinValue.Low) ?
GpioPinValue.High : GpioPinValue.Low;
ledPin.Write(ledPinValue);
}
[...]
This may have been asked several times, but I don't know what to search for..
Anyway. I have a class called Character. Inside of it I want to have a collision component that I have called RectangleCollision. Inside of it there is a function called IsOverlapping that checks for overlap.
I want to have a function that can be modified for each game object. For example create a function called OnBeginOverlap(); that will fire everytime the collision component detects a collision.
Is there any way that I can bind this function as delegate or event? Or something?
You have to read about events and delegates. There are plenty of examples on the web. The easiest I managed to find when I was trying to understand the subject was this:
The Simplest C# Events Example Imaginable
You can also check out the below (you can compile this as console application):
class Character
{
public delegate void OverlappingHandler(Character character, EventArgs e);
public event OverlappingHandler OverlappingEvent;
public void IsOverlapping()
{
bool overlapping = true;
if (overlapping)
{
if (OverlappingEvent != null)
{
OverlappingEvent(this, null);
}
}
}
}
class Program
{
static void Main(string[] args)
{
Character c = new Character();
c.OverlappingEvent += OverlappingEventHandler;
c.OverlappingEvent += OverlappingSecondEventHandler;
c.IsOverlapping();
Console.Read();
}
static void OverlappingEventHandler(Character character, EventArgs e)
{
Console.WriteLine("We have overlapping here!!");
}
static void OverlappingSecondEventHandler(Character character, EventArgs e)
{
Console.WriteLine("Seriously, we have overlapping !!");
}
}
So step by step:
Create a delegate, which is a bridge between your event and the code you want to run when event is triggered. You give parameters to a delegate, which are (object sender, EventArgs e) - in this example sender is the Character class, arguments are used to send additional info - for example type of character.
Create event of our delegate type
In our function IsOverlapping() there would be your logic checking if there is overlapping happening. If there is, you fire up event. You should check first if there is anything connected to the event (hence the if (OverlappingEvent != null)) - if some there is something, fire up the event.
In the Main() you create an instance of the class and...
Subscribe your event handlers to it, so the code that should be executed when the event is triggered. I connected two methods, just to show that you can subscribe more than one.
Now when you run c.IsOverlapping() this is what happens:
your logic to check overlapping runs,
if there is overlapping, there will be a check if OverlappingEvent has code subscribed (it does in Main()),
if it does event will be triggered,
code subscribed to the event runs - in this case your code in Main().
You can compile this as console app and it will display 2 lines:
We have overlapping here!!
Seriously, we have overlapping !!
Hope this helps.
Why does this never get called ?
propertyGrid.KeyDown += new KeyEventHandler(propertyGrid_KeyDown);
private void propertyGrid_KeyDown(object sender, KeyEventArgs e)
{
PoorLittleMethod(); //Never gets called
}
This seems to be the same for Mouse event
I'veread on some forums that PGrid is tricky on raising such events as it Inherits them from Control but does not really Raise them. is that true ? If yes, how to bypass that ?
EDIT 1:
As this seems to be "regular", I find it very light from MS not to specify this explicitely on the MSDN Reference of the propertyGrid class and leave events "as is" as if they were usable, whereas they are not. Tricky things like these are at least usually specified in "notes" inside the refs.
EDIT 2:
I am presently coding a workaround. I'll be posting it soon.
The PropertyGrid's KeyDown property is marked as Browsable(false) - presumably the conclusion we can take from this is that it is not supported in an of itself but is in fact present as a side-effect of its inheritance hierarchy.
Though, interestingly enough, its EditorBrowsable attribute (which is also a designer indicator, for Intellisense and the suchlike) is set as EditorBrowsableState.Advanced - where we would expect EditorBrowsableState.Never should the former presumption be true.
Some information from MSDN forums outlines the why of this situation:
From the tool UI Spy we can see the PropertyGrid is a just a panel and it consists of three Windows Controls. Our KeyDown event should be processed by the child control table.
The structure:
-"pane" "PropertyGrid"
--"pane" "Description Pane"
--"table" "Properties Window"
--"tool bar" "ToolBar"
The suggested solution (also provided in the MSDN link) to overcoming this is to use native system calls to retrieve window/control information, subclass NativeWindow and override the WndProc method to handle the events you like, KeyDown in this case.
You can override this from subclass of PropertyGrid to get some key info from windows message
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
CSharp PropertyGrid Events
// Property grid events can’t be easily subscribed to however there is way to get at the KeyUp event without impacting operation.
// Note: The KeyDown event can be subscribed to in the same manner but the propertygrid is NOT updated with the key presses.
// This code is added in hope it may help someone else solve the problem. It is not offered as a total solution.
// First define a class variable to indicate that events have been added.
private bool m_bPropertyGridEventsAdded = false;
public GlassInfoEntryPage(ViewBase view)
: base(view)
{
InitializeComponent();
// Subscribe to SelectedGridItemChanged
m_PropertyGrid.SelectedGridItemChanged += M_PropertyGrid_SelectedGridItemChanged;
}
// Now define a SelectedGridItemChanged Event Handler
private void M_PropertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
{
int nXlocation;
int nYlocation;
PropertyGrid oPropertyGrid;
Control oControl;
if (m_bPropertyGridEventsAdded == false)
{
oPropertyGrid = (PropertyGrid)sender;
// Search the Property Grid for a PropertyGridView Control so events can be added to it
for (nXlocation = 0; nXlocation < oPropertyGrid.Width; nXlocation += 10)
{
for (nYlocation = 0; nYlocation < oPropertyGrid.Height; nYlocation += 10)
{
oControl = m_glassInfoPropertyGrid.GetChildAtPoint(new Point(nXlocation, nYlocation));
if (oControl != null)
{
if (oControl.GetType().ToString() == "System.Windows.Forms.PropertyGridInternal.PropertyGridView")
{
// Add Events here
oControl.Controls[1].KeyUp += MyCode_KeyUp;
m_bPropertyGridEventsAdded = true;
break;
}
}
}
if (m_bPropertyGridEventsAdded == true)
{
break;
}
}
}
}
// Handle the events
private void MyCode_KeyUp(object sender, KeyEventArgs e)
{
}