Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

How to start a custom drawing tool from a button?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    How to start a custom drawing tool from a button?

    Hi there,

    I am developing an Add-On that has a panel that docks in the current tab of the chart window like the chart trader.

    I have a toggle button on this panel and I want to start a custom drawing tool when the user checks it, and stop the drawing tool when the user unchecks it.

    I have seen examples of how to use a drawing tool from inside an indicator or another drawing tool, but not how to just start the drawing tool, ready for the end user to use, just as if they had gone through the chart menu and started it.

    Can someone provide a sample of how to do this?

    Thanks for your time,

    codeowl

    #2
    Hello codeowl,

    Thank you for your post.

    In your button click event you would call the Execute() method of the drawing tool. For example:
    Code:
    		protected void Button1_Click(object sender, RoutedEventArgs e)
    		{
    			NinjaTrader.Gui.Chart.ChartDrawingToolCommands.Line.Execute(this);
    		}

    Comment


      #3
      Patrick,

      Thanks for the quick response mate, and code sample much appreciated.

      Regards,

      codeowl

      Comment


        #4
        Patrick,

        Following your example I have been able to start an existing drawing tool. However, I have written a custom drawing tool so there is no command for it in:
        Code:
        NinjaTrader.Gui.Chart.ChartDrawingToolCommands
        I tried just creating my own static class and added a command for the tool:
        Code:
        public static class MyCommands
        {
            public static ICommand MyCustomDrawingTool;
        }
        But when I run the MyCustomDrawingTool.Execute(this) method, it gives the error:
        Object reference not set to an instance of an object.

        So how can I start a "custom" Drawing Tool that I have created, from a button?

        Thanks for your time,

        codeowl
        Last edited by codeowl; 04-29-2016, 04:35 AM.

        Comment


          #5
          Hello codeowl,

          I will have to look into this further on my end.

          Comment


            #6
            Patrick,

            Ok great thanks mate. I have built an Add-On and a custom Drawing Tool. A ToggleButton in the Add-On will: turn Stay In Draw Mode on, and then start the custom Drawing Tool. I want the Add-On to get notified with a reference to the relevant drawing object when the MyCustomDrawingTool is stopped by either the end user pressing escape, or going to the Drawing Tools menu and unchecking Stay In Draw Mode. (I looked into using OnStateChange and State == State.Terminated, but this state seems to be raised some times even when the tool is just starting. So I need something more robust)

            Also, I need to know how to stop a "custom" Drawing Tool in a button click event. As I am going to put Stay In Draw Mode on before I start the custom Drawing Tool, maybe it is as simple as toggling this off to stop the current Drawing Tool?

            The scenario is I will have a toggle button that will be used to start the drawing tool (in stay on mode) and turn it off. So I want to keep that checked state of the toggle button in sync with the drawing tool. Eg; if the user presses escape to stop the drawing tool, I want to uncheck the toggle button.

            Also the Add-On which starts the custom Drawing Tool needs to be able to subscribe to the drawing tools events. I have created some events in my custom drawing tool that get raised when an edit or move are completed. I didn't see a way this was possible using the Execute method of starting the drawing tool, as I have no reference to an instance of the drawing tool.

            Also, as the goal is to collect data about the regions highlighted with the custom Drawing Tool I need to be able to get notified when a drawing made by the custom drawing tool is deleted. I was hoping there would be an observable collection of Drawings in the ChartObject that I could subscribe to CollectionChanged event, however this does not seem to be the case, and while there is an Indicators property and a Strategies property, there is no Drawings property. How can I get notified in the Add-On when a Drawing created by my custom drawing tool is deleted by selecting and pressing the delete key, or right clicking and selecting Remove?

            Also is there a way to programmaticly select a specific drawing on the chart?

            And a way to programmaticly delete a specific drawing from the chart?

            How can I achieve these goals?

            Regards,

            codeowl


            Update 1:
            I have found the following documentation:


            It would be great if these objects were made accessible in an ObservableCollection via the ChartWindow.ActiveChartControl object. This way Add-on's could access it easily react when a drawing was added/removed.

            Update 2:
            From the research I have done it appears there is no way to delete a User Drawn DrawObject from the chart, unless you remove them all and redraw everything but the one you wanted to remove and even then it is a real hack, plus I can't even see the method he is using when I look at the ChartControl with Reflector:
            Hi, can it be the function RemoveDrawObject() does not delete objects which the user has added manually to the chart? I checked it many times and that far I do not see any problem/bug in the code. I can remove objects which the indicator created but when I try to remove an object which has been added by the user to the chart it does not work. Neither when I reference it by the tag, nor by the object id directly [RemoveDrawObject() has 2 overloads]. The behaving does not change if I lock/unlock the object or …


            I am now able to get an event raised when:
            - A new drawing with the custom drawing tool is completed
            - An existing drawing made with the custom drawing tool has been copied and is pasted into the chart
            - An existing drawing made with the custom drawing tool is moved
            - An existing drawing made with the custom drawing tool is edited

            I could use a singleton class to get around not having an instance of the DrawingTool when I start it, and just code the Drawing Tool to use the singleton to communicate with my Add-on.

            I found the following post:


            Which shows how to subscribe to the CollectionChanged event in ChartControl/ChartPanel/ChartScale.ChartObjects (which is an ObservableCollection). There is no documentation for the ChartScale.ChartObjects property, but the ChartPanel object also has a ChartObjects property (which of course is not an ObservableCollection) that is documented and the documentation would lead us to believe that this collection does contain DrawingTools.


            I have subscribed to this collection on all ChartScales where the property was not null from an Add-On, in a button click event. I opened the Chart Window, after the chart loaded I clicked on the button to wire up the event handlers on the ChartScale.ChartObjects, and then I added and removed a drawing using a drawing tool. The event handlers had calls to the Print function to show the event was raised. The event was not raised. Does this only work when done from in an indicator?

            Any help here would be much appreciated.

            Update 3:
            Ok just got a chance to test out the ChartControl/ChartPanel/ChartScale.ChartObjects.CollectionChanged event from an indicator and it does work as expected when running from an indicator, so I can just add an indicator to the mix with the singleton class to cover notifying the Add-on of removal of drawings created with the custom drawing tool.

            So I still need to know:
            - How to start the Custom Drawing Tool from a button in an Add-on.
            - How to get notified when the Custom Drawing Tool is stopped by the end user. (eg; pressing escape, or unticking Stay In Draw Mode.
            - How to stop the Custom Drawing Tool from a button in an Add-on.
            - How to add/remove an indicator to a chart from code in an Add-on.

            Any help here would be much appreciated...

            Update 4:
            Ok so it appears that it is not possible to start an indicator from an Add-on. For some reason this can only be done from Strategies.

            It would be fantastic if this could be done from an Add-on as then it is one less thing the user has to do in order to use the Add-on. The custom indicator I have created has no UI element (eg; does not plot lines or icons), and it's ownly purpose is to detect when a drawing is removed from the chart, as there is no other way to do it. So the end user should not have to manually add an indicator to the chart for this..... the Add-on should be able to add it from code, or better still the add-on should not need an indicator to detect when a drawing is removed from the chart, the add-on should be able to do this itself, that would really be the best solution.

            Any help here would be much appreciated...

            Regards,

            codeowl
            Last edited by codeowl; 05-07-2016, 06:04 AM. Reason: Added some more detail

            Comment


              #7
              Patrick,

              How did you go with looking into this further. I have continued to work on the problem, and have updated my previous post with items I have been able to work out.

              Biggest issues at the moment are as follows:

              - No way to start custom Drawing Tool.
              - No way to detect when a custom Drawing Tool is disengaged. Eg; User presses escape or unticks stay in drawing mode. (see details on previous post on this)
              - No way in an Add-on to detect if a drawing object was removed from the chart by the end user. (see details on previous post on this)
              - No way to programmatically add an indicator to a chart. Only reason I am using an indicator is cause the previous item doesn't work. There is no value to the end user having this indicator on the chart, it just needs to be there for the Add-on to detect if a drawobject is removed. So it would be a pain to have to get the user to add an indicator to the chart that has no visual output.

              Other issues are:
              - No way to delete a user drawn object. I have created a custom drawing tool to allow the user to collect data from the chart and send it to the Add-on. However when the Add-on data collection panel is closed there is no point having the drawings on the chart anymore. So I need to be able to remove them.

              Any help would be much appreciated.

              Regards,

              codeowl

              Comment


                #8
                No update on this as I am still looking into this on my end.

                Comment


                  #9
                  Patrick,

                  Ok great, thanks for the feedback mate, good to know you are still on the job! I will look forward to discussing solutions :-)

                  Regards,

                  codeowl

                  Comment


                    #10
                    Patrick,

                    One more issue I have just identified. The help documentation gives the following example of adding a drawing to a chart from code:


                    Code:
                    // Fills in the region between the startBar and endBar
                    Draw.RegionHighlightX(this, "tag1", 10, 0, Brushes.Blue);
                    Note the first parameter (this), needs to be an object that inherits from NinjaScriptBase.
                    So, although the help page above's sample code gives absolutely no context at all, we will assume that the line of code above was designed to be executed from within an indicator.

                    I am wanting to draw on a chart from an Add-on. Is this possible, and if so how do I do it?
                    I have found NinjaTrader_Jesse's great video where he goes into detail of how to use a drawing tool from inside another drawing tool... I thought this may have helped as a Drawing Tool does not inherit from NinjaScriptBase. But the example relies in the first Drawing Tool being called from an Indicator which passes in itself as the owner... so unfortunately this does not help me. (but still great work on the vid from Jesse!)


                    So my goal is to be able to draw a region on the chart at a specific location on an event like a button click in a Add-on.

                    How can I achieve this?

                    Update 1:
                    Have been doing some testing. The following call works ok:
                    Code:
                    Draw.RegionHighlightX(this, "tag1", 10, 0, Brushes.Blue);
                    However this one does nothing, no error, but no drawing either:
                    Code:
                    Draw.RegionHighlightX(
                        _AIIndicator, 
                        "tag1", 
                        new System.DateTime(2016, 05, 10, 20, 36, 02, 289), 
                        new System.DateTime(2016, 05, 10, 21, 08, 51, 074), 
                        System.Windows.Media.Brushes.Blue);
                    See the attached images that show that there are bars at these times. I have not modified the RegionHighlightX code at all. My custom drawing tool is based on the RegionHighlightX, and I want to be able to create drawings based on time as in the example above, however it appears this doesn't work.....
                    Can you please let me know if this is a bug, or I am doing something wrong?

                    Update 2:
                    Also I find that when creating the drawing from code using the above example (the one that works), if price is not moving, the Drawing does not get drawn on the chart until you move the scroll bar... which I assume triggers a render event. Is there a way to get it to render directly after I have called Draw.RegionHighlightX(...)?
                    The tool will be used when the market is over, so I can't rely on price moves to render the drawing...

                    Update 3:
                    Ok I fixed the issue with the RegionHighlightX Draw method.
                    I replaced the following two lines:
                    Code:
                    startAnchor = new ChartAnchor(startTime, startY, currentBar, chartControl);
                    endAnchor = new ChartAnchor(endTime, endY, currentBar, chartControl);
                    With:
                    Code:
                    startAnchor = new ChartAnchor(startTime, 0, chartControl);
                    endAnchor = new ChartAnchor(endTime, 0, chartControl);
                    I am guessing that was a bug.......


                    Update 4:
                    I found that I can get a drawing created from code to appear straight away if I call:
                    _Indicator.ForceRefresh();

                    Not sure this is the best approach. Please let me know if there is a better way of doing it. Ideally we would be able to draw from code and detect drawings removed from the chart without needing to use an indicator.

                    Regards,

                    codeowl
                    Attached Files
                    Last edited by codeowl; 05-14-2016, 11:13 PM. Reason: Added updates

                    Comment


                      #11
                      Hi codeowl

                      Have you found a way to start a custom drawing tool from a button yet?

                      I have modified the stock fib tool and would like to start it from a chart toolbar button, but have so far only got the same error as you had.

                      Comment


                        #12
                        FatCanary,

                        Sadly I am still waiting for resolution to every issue mentioned in this thread that I have not solved myself.....

                        Patrick,

                        How did you go looking into these issues mate, did you come up with any solutions?

                        To make it easyer than going over this entire thread to get all the detail, here is a summary of outstanding issues/questions:
                        • No way to start a custom drawing tool from a button in an add-on.
                        • No way to stop a custom drawing tool from a button in an add-on.
                        • No way to get notified that a custom drawing tool has been stopped by the end user.(1)
                        • Is there a way to programmaticly select a specific drawing on the chart?
                        • Is there a way to programmaticly scroll a specific drawing into view?
                        • No way to delete a User Drawn DrawObject from the chart.(2)
                        • No way for the end user to modify drawnings created from code. (3)
                        • No way to do a drawing without using an indicator. (4)
                        • No way to add an indicator to a chart with code. (4)
                        • I found that I can get a drawing created from code to appear straight away if I call: _Indicator.ForceRefresh(); Not sure this is the best approach. Please let me know if there is a better way of doing it.


                        Additional Notes:
                        (1) The scenario is I will have a toggle button that will be used to start the drawing tool (in stay on mode) and turn it off. So I want to keep that checked state of the toggle button in sync with the drawing tool. Eg; if the user presses escape to stop the drawing tool, I want to uncheck the toggle button.

                        (2) I have created a custom drawing tool to allow the user to collect data from the chart and send it to the Add-on. However when changing functions in the Add-on I need to be able to remove the drawings.

                        (3) I want the user to be able to load in a list of previos selections and edit them. This can't be done as you can't modify drawings created from code.

                        (4) Having to use an indicator to add a drawing on a chart, and detect when it is removed, means that I need to create an indicator that has no other purpose than this. Eg; id does not plot any lines on the chart or give the end user any value. Yet due to the inability to add an indicator to the chart via code, the end user is forced to add the indicator themselfs, for no perceivable benifite, other than the AddOn won't work without it.

                        Regards,

                        codeowl
                        Last edited by codeowl; 06-02-2016, 05:25 PM. Reason: Added summary for Patrick

                        Comment


                          #13
                          Originally posted by codeowl View Post

                          But when I run the MyCustomDrawingTool.Execute(this) method, it gives the error:
                          Object reference not set to an instance of an object.


                          Am I correct in thinking that error message signifies a bug?

                          I've run out of ideas and can't see the point of trying to pursue the issue further if this is actually a bug.

                          Comment


                            #14
                            FatCanary,

                            No I don't think it is bug a mate... I think it was never designed to expose this functionality to Add Ons.
                            The ChartDrawingToolCommands class used here:
                            Code:
                            NinjaTrader.Gui.Chart.ChartDrawingToolCommands.Line.Execute(this);
                            Is an internal (internal as in designed for use by NT not 3rd party developers like us, the class itself is actually public as far as accessibility goes) static class, and the properties like Line are ICommand's
                            Code:
                            public static ICommand Line;
                            Then they have set these up as follows in the static constructor of the ChartDrawingToolCommands class:
                            Code:
                            ChartDrawingToolCommands.Line = new RoutedCommand("Line", typeof(ChartDrawingToolCommands));
                            In order to use the command in an application, event handlers which define what the command does must be created. We need an example of what to put in these event handlers to implement our own solution.
                            This is what I have asked NT/Patrick for.... maybe his is waiting on the dev team to get back to him with an answer....

                            But as yet we have no solution for this or any of the other items on the list....

                            Regards,

                            codeowl
                            Last edited by codeowl; 06-04-2016, 03:03 AM.

                            Comment


                              #15
                              Thanks for the extra info codeowl.

                              I've done some playing around with Routed event handlers, but I've got nothin'

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by judysamnt7, 03-13-2023, 09:11 AM
                              4 responses
                              59 views
                              0 likes
                              Last Post DynamicTest  
                              Started by ScottWalsh, Today, 06:52 PM
                              4 responses
                              36 views
                              0 likes
                              Last Post ScottWalsh  
                              Started by olisav57, Today, 07:39 PM
                              0 responses
                              7 views
                              0 likes
                              Last Post olisav57  
                              Started by trilliantrader, Today, 03:01 PM
                              2 responses
                              21 views
                              0 likes
                              Last Post helpwanted  
                              Started by cre8able, Today, 07:24 PM
                              0 responses
                              10 views
                              0 likes
                              Last Post cre8able  
                              Working...
                              X