Solved

Implementing Plugins and Custom form collection classes

Posted on 2004-09-07
4
313 Views
Last Modified: 2013-11-18
I would like to implement the following architecture in a Windows .NET program. I first query a database and return several Data Tables stored in a single Dataset. The user has several windows selectable "View2D", "View3D", "ViewGraph", etc, etc. to look at the data.

I want to allow the user to open any number of windows and then iterate through them updating the displays of data as the data changes. The Dataset is working OK, the problem is I need an efficient custom collection class to hold the different types of forms that will display data. All the forms have an "->Update(dataset * ds)" call which will allow them to do their thing with the dataset tables.

I also want to attach a plug in which will allow me to dynamically load user defined plug in forms, add them to the collection and call them also. I put these two together because I think the logic has to work together.

Here is my (relevant) code so far.

// Create a new custom collection
DisplayCollection * DataDisplays = new DisplayCollection() ;


// Later in the code
Void ToolBarMain_ButtonClick(System::Object * sender, System::Windows::Forms::ToolbarButtonClickEvent * e)
{
     if (e->button->Tag == S"View2D")
     {
           View2D * View2DDisplay = new View2D() ;              // this is a custom form
           // Create a new display and add it to the collection using the name as key
           Display * NewDisplay = new Display (View2DDisplay, e->Button->Tag->ToString()) ;
           DataDisplays->Add(NewDisplay) ;
           View2DDisplay->Text = NewDisplay->Key ;
           View2DDisplay->Show() ;
     }
     else if (e->button->Tag == S"View3D")
     {
          View3D * View3DDisplay = new View3D() ;              // this is a custom form
           // Create a new display and add it to the collection using the name as key
           Display * NewDisplay = new Display(View3DDisplay, e->Button->Tag->ToString()) ;
           DataDisplays->Add(NewDisplay) ;
           View3DDisplay->Text = NewDisplay->Key ;
           View3DDisplay->Show() ;
     }
     else if (e->button->Tag == S"ViewGraph")
     {
          ViewGraph* ViewGraphDisplay = new ViewGraph() ;              // this is a custom form
           // Create a new display and add it to the collection using the name as key
           Display * NewDisplay = new Display(ViewGraphDisplay , e->Button->Tag->ToString()) ;
           DataDisplays->Add(NewDisplay) ;
           ViewGraphDisplay->Text = NewDisplay->Key ;
           ViewGraphDisplay->Show() ;
     }
    else if (etc., etc....)  // This can be many different types of forms and later plugin forms


     // Later again in the code I want to loop through the forms continually updating the data
     // by calling each form loaded. I plan on also implementing a data page which will allow the
     // user to attach different pages to different tables with some default operations.
     do
     {

          IEnumerator * ie = DataDisplays->GetEnumerator() ;
          while (ie->MoveNext())
          {
                // I want to pull each form out and call its "->Update(MyDataSet)" function.      
                 Display * CallDisplay = dynamic_cast<Display *> (ie->Current) ;
                 
                if (CallDisplay->KeyType == S"View2D")
                {  
                    dynamic_cast<View2D *>(CallDisplay->CurrentDisplay)->Update(MyDataSet) ;
                }
                else if (CallDisplay->KeyType == S"View3D")
                {
                    dynamic_cast<View3D *>(CallDisplay->CurrentDisplay)->Update(MyDataSet) ;
               }
                else if (CallDisplay->KeyType == S"ViewGraph")
                {
                    dynamic_cast<ViewGraph *>(CallDisplay->CurrentDisplay)->Update(MyDataSet) ;
               }
                else
                {
                          // Need to handle all other plugins here !!!!!!!!!1111
                }

          }

     } while (ProgramRunning == true) ;

}



__gc class Display
{

     public : Display(Object * NewDisplay, String * NewKey)
     {
            FormCounter++ ;  // This allows me to give my forms unique key names
           // Store the new form, a unique key for the list, and a form type identifier
           this->m_display = NewDisplay ;
           this->m_key = String::Concat(FormCounter.ToString("000"), " ", NewKey ) ;
           this->m_keyType = NewKey ;
     }

         // Return the form, its unique key or the form type
     __property Object * get_CurrentDisplay() { return this->m_display ;}
     __property String * get_Key() { return this->m_key ;}
     __property String * get_KeyType() { return this->m_keyType ;}

     private:
     static FormCounter = 0 ;
     Object * m_display ;
     String * m_key ;
     String * m_keyType ;

}


__gc class DisplayCollection : public IEnumerable
{

     private:
         SortedList * m_DisplayList ;
         bool m_WasModified ;

    public :
         DisplayCollection()
         {
               m_DisplayList = new SortedList() ;
               m_WasModified = false ;
          }

          __gc class DisplayEnumerator : public IEnumerator
          {
                private:
                        DisplayCollection * MyCollection ;
                        int position ;

                public:
                        DisplayEnumerator(DisplayCollection * NewDisplayCollection)
                        {
                             this->MyCollection = NewDisplayCollection ;
                             position = -1 ;
                        }

                        Object * get_Current()
                        {
                            if (position < 0 || position >= MyCollection->m_DisplayList->Count || MyCollection=>m_WasModified)
                                          throw new InvalidOperationException() ;
                            return MyCollection->m_DisplayList->GetByIndex(position) ;
                        }
           
                        void Reset()
                        {
                            MyCollection->m_WasModified = false ;
                            position = -1 ;
                         }
                         
                         bool MoveNext()
                         {
                             if (MyCollection->m_WasModified) throw new InvalidOperationException() ;
                             position++ ;
                             return (position < MyCollection->m_DisplayList->Count) ;
                          }
             } ;

          IEnumerator * GetEnumerator()
          {
              m_WasModified = false ;
              return __try_cast<IEnumerator *>(new DisplayEnumerator(this)) ;
          }

          void Add(Display * NewDisplay)
          {
               m_WasModified = true ;
               m_DisplayList->Add(NewDisplay->Key, NewDisplay) ;
               return ;
          }
} ;


I want this to be as efficient as possible and then to expand the architecture to allow plug ins to be loaded. The plugins will be DLLs in a subdirectory which only will be read at program start. There will be no dynamic loading/unloading at program execution. I need them to modify the toolbar (add icon), load a custom form defined in the DLL when the button is clicked, and have built in functionality such as provide pie charts, strip charts, special applications, etc. etc. Then I want to add those forms to the collection and dynamically call them. The main program will call the "->Update(MyDataSet)" routine in each custom form. The custom forms take the data set and work with the appropriate data tables by setting local variables in the form (attaching data sources).

WHEW!!!!!!!!!!!! I think this is a tough one so I have to go maximum points on this.

0
Comment
Question by:Slovikosky
  • 2
4 Comments
 
LVL 19

Accepted Solution

by:
drichards earned 500 total points
ID: 12033255
Let's see if this gets you going in the direction you need.  First step is to get the plugin forms loading.  This is relatively easy.  To do this, create a class library project and put a Windows form in it.  This will be the base class for your plugin forms.  You probably don't need to add anything beyond the default form yet.

Once the base form compiles, create a main project and reference the base form library (use "Add Reference" and reference the base form project).  This is where your main form goes.  Add Your toolbar and whatever else you need.  You probably want to create a tollbar, initially empty, that holds just the plugin buttons.  In the constructor of the main form, add code to go look for dll files in the plugin directory.  For each dll found, load the assembly and load the types.  Check for types whose BaseType FullName matches the name of your form base class.  Create an instance of each matching form class and store the instance in an array or other collection.  Also create a toolbar button for each matching form class.  The button index on the toolbar should be the same as the form index in the collection.

Add a handler (you can use the same one) to handle plugin button clicks.  Check the index of the button and show the corresponding form from the plugin form collection.  Once you get to this point, you should be able to load and display the forms.  You may want to have another collection of forms to keep track of which formas are currently displayed.  This is not necessary as you can just check whether forms are visible.

Now you can go back to the base form and add the generic methods to hand off datasets to the forms.  Then add thecustom rendering to the plugin forms.

Conceptually this does not seem too hard.  If you've already got controls or code to do the data rendering, it should be pretty easy.
0
 
LVL 19

Expert Comment

by:drichards
ID: 12033267
If you don't want to keep instances of all the plugins around all the time, you could put the Type's in the initial array and create instances when you want to show the forms.  Then you wold definitely need a second collection to keep track of currently instantiated forms.  This is what your example code was driving at.

0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
In this article you will learn how to create a free basic website on Bitbucket, a git service provider. Polymer creates dynamic HTML components, which allow more flexibility than static HTML. This tutorial uses Ubuntu Linux but can also be done on W…
The purpose of this video is to demonstrate how to set up the WordPress backend so that each page automatically generates a Mailchimp signup form in the sidebar. This will be demonstrated using a Windows 8 PC. Tools Used are Photoshop, Awesome…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

26 Experts available now in Live!

Get 1:1 Help Now