Toggle with one click

Thank you very much , now looks better with highlight.

image

using System;
using System.Collections.Generic;
using Grasshopper.Kernel;
using System.Drawing;
using Grasshopper.GUI;
using Grasshopper.GUI.Canvas;
using Grasshopper.Kernel.Types;

namespace singleClick  //adapt to your project
{

    public class SpecialIntegerObject : GH_Param<GH_Boolean>
    {
        public SpecialIntegerObject() :
          base(new GH_InstanceDescription("Toggle", "Toggle", "True/False", "Params", "Input"))
        { }

        public override void CreateAttributes()
        {
            m_attributes = new SpecialIntegerAttributes(this);
        }

        protected override Bitmap Icon
        {
            get
            {
                return Toggle_new.Properties.Resources.tog;

            }
        }
        public override GH_Exposure Exposure
        {
            get
            {
                return GH_Exposure.primary | GH_Exposure.obscure;
            }
        }
        public override System.Guid ComponentGuid
        {
            get { return new Guid("{520F0976-35D1-4CC4-925B-2A07BFF17007}"); }
        }

        //private int m_value;
        private bool m_value;
        public bool Value
        {
            get { return m_value; }
            set { m_value = value; }
        }
        protected override void CollectVolatileData_Custom()
        {
            VolatileData.Clear();
            AddVolatileData(new Grasshopper.Kernel.Data.GH_Path(0), 0, new GH_Boolean(Value));
        }

        public override bool Write(GH_IO.Serialization.GH_IWriter writer)
        {
            writer.SetBoolean("SpecialInteger", m_value);
            return base.Write(writer);
        }
        public override bool Read(GH_IO.Serialization.GH_IReader reader)
        {
            reader.TryGetBoolean("SpecialInteger", ref m_value);
            return base.Read(reader);
        }
    }

    public class SpecialIntegerAttributes : GH_Attributes<SpecialIntegerObject>
    {

        public SpecialIntegerAttributes(SpecialIntegerObject owner)
          : base(owner)
        {

        }

        public override bool HasInputGrip { get { return false; } }
        public override bool HasOutputGrip { get { return true; } }

        private const int ButtonSize = 34;

        public bool bo;

        public Font font;
        
        //Our object is always the same size, but it needs to be anchored to the pivot.
        protected override void Layout()
        {
            //Lock this object to the pixel grid. 
            //I.e., do not allow it to be position in between pixels.
            Pivot = GH_Convert.ToPoint(Pivot);
            Bounds = new RectangleF(Pivot, new SizeF((float)(ButtonSize * 2.5), ButtonSize));
        }
        /// <summary>
        /// This method returns the button at the given column and row offsets.
        /// </summary>
        private RectangleF TextBound()
        {
            int x = Convert.ToInt32(Pivot.X);
            int y = Convert.ToInt32(Pivot.Y);
            return new RectangleF(new PointF(x + 27, y), new SizeF(55, ButtonSize));
        }
        private Rectangle Button()
        {
            int x = Convert.ToInt32(Pivot.X);
            int y = Convert.ToInt32(Pivot.Y);
            return new Rectangle(x + 4 , y + 4, ButtonSize - 8, ButtonSize - 8);
        }
        /// <summary>
        /// Gets the value for the given button.
        /// </summary>
        public override GH_ObjectResponse RespondToMouseDown(GH_Canvas sender, GH_CanvasMouseEvent e)
        {
            //On one click we'll set the owner value.
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                RectangleF button = Button();
                if (button.Contains(e.CanvasLocation))
                {
                    bo = !bo;
                    Owner.Value = bo;
                    Owner.ExpireSolution(true);
                    return GH_ObjectResponse.Handled;
                }

            }
            return base.RespondToMouseDown(sender, e);

        }
        public override void SetupTooltip(PointF point, GH_TooltipDisplayEventArgs e)
        {
            base.SetupTooltip(point, e);
            e.Description = "Toggle";
        }

        /// <summary>
        /// This object is rendered as a 1x3 grid of capsules.
        /// </summary>

        protected override void Render(GH_Canvas canvas, Graphics graphics, GH_CanvasChannel channel)
        {
            if (channel == GH_CanvasChannel.Objects)
            {
                //Render output grip.
                GH_CapsuleRenderEngine.RenderOutputGrip(graphics, canvas.Viewport.Zoom, OutputGrip, true);

                Rectangle button = Button();
                RectangleF bound = Bounds;
                RectangleF text = TextBound();
                font = new Font("Verdana", 9);
                Color color;

                if (Owner.Value == true)
                {
                    bo = true;
                    color = Color.YellowGreen;
                }
                else
                {
                    bo = false;
                    color = Color.LightGray;
                }

                GH_Capsule capsule = GH_Capsule.CreateTextCapsule(bound, text, GH_Palette.Transparent, Owner.Value.ToString().ToUpper(), font, 17, 1) ;
                capsule.HighlightShape.Reset();
                capsule.HighlightShape.AddPath(capsule.OutlineShape, true);
                capsule.Render(graphics, Color.DarkGray);

                capsule.Dispose();

                GH_Capsule buttonb = GH_Capsule.CreateCapsule(button, GH_Palette.Transparent, 16, 1);
                
                buttonb.HighlightShape.Reset();
                buttonb.HighlightShape.AddPie(button, 180f, 180f);
                buttonb.Render(graphics, color);

                buttonb.Dispose();


            }
        }
    }
}
1 Like

Hello, how we can add option to publish the component to RPC.
I read this but i don’t understand how it work

This is an idea to design a component shape and get the values needed , a standalone application for this will be very useful.

I have zero experience with that, sorry.
btw, you could make another topic for this, I guess you’d have more success to have an answer like that.

not sure to understand what you’d like here. A script inside vs? or a componenet in grasshopper? what would that help?

Thanks , it’s related to this topic.
Scripting with c# and using visual studio is complicated , python is easier but limited.


For the second question it’s an idea that creating app or tool to design a component is possible, but it need a professional who know everything and all details to make this and convert the result to a useful script.

An Interface is a great concept to loosely couple code within a strongly types language like C# . The most common example is IEnumerable. Which basically means my function only requires something which acts as a collection like a list, queue, array etc. It doesn’t matter what it is, I just want to iterate over it with a foreach loop. So it needs certain code to allow you to do that. Its a contract of ensuring that an object implebtation contains certain class members (properties, methods, events …)
Now in this example it likely means if your Component implements that particular interface the Rcp panel is aware of it. It will require you to define a ‚Publish’ method. I guess this method should tell the RCP panel how it looks inside that, which in there must be an Eto control. So it could be a simple Togglebutton control with an Label. But you‘ll probably need to define that. How this is supposed to work in detail can be found out if you use ILSpy to see how it works for another GH_Component (e.g.Togglebutton).

Hi @seghierkhaled
Is it possible to created smaller width of Click component so many of them together?

I will try , actually i don’t have visual studio 2019, and the new version 2022 not tested yet with the code

Or is the desired width can be controlled by users?

No this is not possible with component unless you modify the code posted here

private const int ButtonSize = 34;

Can I control the width here?

Yes try it
And there are other settings undet this line

protected override void Layout()
        {
            Pivot = GH_Convert.ToPoint(Pivot);
            Bounds = new RectangleF(Pivot, new SizeF(ButtonSize * 2, ButtonSize)); 
        }

you’d control the size here. remember that the button size is related to the layouts pivot.you’ll probably need to ajust both.

private Rectangle Button()
        {
            int x = Convert.ToInt32(Pivot.X);
            int y = Convert.ToInt32(Pivot.Y);
            return new Rectangle(x + 4, y + 4, ButtonSize * 2 - 8, ButtonSize - 8);
        }
1 Like