samrrr
Topic Author
Posts: 12
Joined: 05 Jul 2022, 12:39

Is possible do C++: public override UIElement Child

09 Dec 2022, 15:02

C# is
        public override UIElement Child
        {
            get { return base.Child; }
            set
            {
                if (value != null && value != this.Child)
                    this.Initialize(value);
                base.Child = value;
            }
        }
        
How do same in С++?
 
User avatar
jsantos
Site Admin
Posts: 3919
Joined: 20 Jan 2012, 17:18
Contact:

Re: Is possible do C++: public override UIElement Child

12 Dec 2022, 12:57

Could you please indicate the base class you are trying to extend? We expose the following virtual functions in Visual:
/// Gets the number of child elements for the Visual
/// \remarks Each visual implementation will decide how to store visual children
virtual uint32_t GetVisualChildrenCount() const;

/// Returns the specified Visual in the parent VisualCollection
/// \remarks Each visual implementation will decide how to store visual children
virtual Visual* GetVisualChild(uint32_t index) const;
 
samrrr
Topic Author
Posts: 12
Joined: 05 Jul 2022, 12:39

Re: Is possible do C++: public override UIElement Child

20 Dec 2022, 21:46

I try extend Border like this:
    // https://stackoverflow.com/questions/741956/pan-zoom-image
    public class ZoomBorder : Border
    {
        public override UIElement Child
        {
            get { return base.Child; }
            set
            {
                if (value != null && value != this.Child)
                    this.Initialize(value);
                base.Child = value;
            }
        }

        public void Initialize(UIElement element)
        {
            this.child = element;
            if (child != null)
            {
                TransformGroup group = new TransformGroup();
                ScaleTransform st = new ScaleTransform();
                group.Children.Add(st);
                TranslateTransform tt = new TranslateTransform();
                group.Children.Add(tt);
                child.RenderTransform = group;
                child.RenderTransformOrigin = new Point(0.0, 0.0);
                this.MouseWheel += ChildMouseWheel;
                this.MouseLeftButtonDown += ChildMouseLeftButtonDown;
                this.MouseLeftButtonUp += ChildMouseLeftButtonUp;
                this.MouseMove += ChildMouseMove;
                this.PreviewMouseRightButtonDown += new MouseButtonEventHandler(
                  ChildPreviewMouseRightButtonDown);
            }
        }

        public void Reset()
        {
            if (child != null)
            {
                // reset zoom
                var st = GetScaleTransform(child);
                st.ScaleX = 1.0;
                st.ScaleY = 1.0;

                // reset pan
                var tt = GetTranslateTransform(child);
                tt.X = 0.0;
                tt.Y = 0.0;
            }
        }

        private void ChildMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (child != null)
            {
                var st = GetScaleTransform(child);
                var tt = GetTranslateTransform(child);

                double zoom = e.Delta > 0 ? 1.3 : 1 / 1.3;

                Point relative = e.GetPosition(child);
                double absoluteX;
                double absoluteY;

                absoluteX = relative.X * st.ScaleX + tt.X;
                absoluteY = relative.Y * st.ScaleY + tt.Y;

                st.ScaleX *= zoom;
                st.ScaleY *= zoom;

                tt.X = absoluteX - relative.X * st.ScaleX;
                tt.Y = absoluteY - relative.Y * st.ScaleY;
            }
        }

        private void ChildMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (child != null)
            {
                var tt = GetTranslateTransform(child);
                start = e.GetPosition(this);
                origin = new Point(tt.X, tt.Y);
                this.Cursor = Cursors.Hand;
                child.CaptureMouse();
            }
        }

        private void ChildMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (child != null)
            {
                child.ReleaseMouseCapture();
                this.Cursor = Cursors.Arrow;
            }
        }

        private void ChildPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Reset();
        }

        private void ChildMouseMove(object sender, MouseEventArgs e)
        {
            if (child != null)
            {
                if (child.IsMouseCaptured)
                {
                    var tt = GetTranslateTransform(child);
                    Vector v = start - e.GetPosition(this);
                    tt.X = origin.X - v.X;
                    tt.Y = origin.Y - v.Y;
                }
            }
        }

        private TranslateTransform GetTranslateTransform(UIElement element)
        {
            return (TranslateTransform)((TransformGroup)element.RenderTransform)
              .Children.First(tr => tr is TranslateTransform);
        }

        private ScaleTransform GetScaleTransform(UIElement element)
        {
            return (ScaleTransform)((TransformGroup)element.RenderTransform)
              .Children.First(tr => tr is ScaleTransform);
        }

        private UIElement child = null;
        private Point origin;
        private Point start;
    }
 
samrrr
Topic Author
Posts: 12
Joined: 05 Jul 2022, 12:39

Re: Is possible do C++: public override UIElement Child

22 Dec 2022, 07:52

I see Child functions not virtual, i cant override its by simple virtual func.
    /// Gets or sets child element
    //@{
    UIElement* GetChild() const;
    void SetChild(UIElement* child);
    //@}
 
User avatar
sfernandez
Site Admin
Posts: 2995
Joined: 22 Dec 2011, 19:20

Re: Is possible do C++: public override UIElement Child

27 Dec 2022, 12:09

Hi, the Decorator provides a virtual method for Child property changes, so you can override it to register/unregister any event handlers you want on the child:
void ZoomBorder::OnChildChanged(UIElement* oldChild, UIElement* newChild) override
{
  if (oldChild != nullptr) { // unregister events... }
  if (newChild != nullptr) { // register events... }
}
 
Xaron
Posts: 6
Joined: 27 Feb 2022, 19:23

Re: Is possible do C++: public override UIElement Child

25 Aug 2023, 14:40

I second that question but this time for the Unity C# side. The UIElement Child is defined like that so I cannot override it:
  public UIElement Child {
    set {
      NoesisGUI_PINVOKE.Decorator_Child_set(swigCPtr, UIElement.getCPtr(value));
    } 
    get {
      IntPtr cPtr = NoesisGUI_PINVOKE.Decorator_Child_get(swigCPtr);
      return (UIElement)Noesis.Extend.GetProxy(cPtr, false);
    }
  }
Setting this function as virtual solves it but I'm not sure it has potential side effects? On my end everything else seems to work fine.

And I don't see a virtual method for Child property changes in the C# decorator class...
 
User avatar
sfernandez
Site Admin
Posts: 2995
Joined: 22 Dec 2011, 19:20

Re: Is possible do C++: public override UIElement Child

30 Aug 2023, 10:49

Setting this function as virtual solves it but I'm not sure it has potential side effects?
If you call the base class getter/setter in your override it won't cause problems. The limitation about making it just virtual (without more code on our C++/C# bindings) is that any call in C++ code to Decorator::GetChild() won't call the override in the C#, but if you are only overriding it for the setter it will be safe.
I don't see a virtual method for Child property changes in the C# decorator class
Could you please create a ticket about this?

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 26 guests