?
Solved

Implementing Plugins and Custom form collection classes

Posted on 2004-09-07
4
Medium Priority
?
324 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 19

Accepted Solution

by:
drichards earned 2000 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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Before we dive into the marketing strategies involved with creating an effective homepage, it’s crucial that EE members know what a homepage is. In essence, a homepage is the introductory, or default page, of a website that typically highlights the …
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 tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses
Course of the Month12 days, 11 hours left to enroll

777 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